Commit 6e304b6b authored by Nguyen, Thien Minh's avatar Nguyen, Thien Minh
Browse files

Merge branch 'master' into tnguyen/ftqc-shots

parents cc350142 4b40a33c
Loading
Loading
Loading
Loading
+0 −11
Original line number Diff line number Diff line
@@ -32,15 +32,4 @@ int main() {

  std::cout << "<H> = " << energy << "\n";

  // note you could also call execute_async() -> Handle and
  // manually qcor::sync(handle)

  // or you could call execute(initial_params:vector<double>)
  // or you could call execute_async(initial_params:vector<double>)
  // or you could call execute(optimizer, initial_params:vector<double>)
  // or you could call execute(optimizer)

  // If you wanted to provide initial-parameters, you can
  // query the size of vector you need with
  // qaoa.n_parameters() (also have n_gamma(), n_beta(), and n_steps())
}
 No newline at end of file
+1 −8
Original line number Diff line number Diff line
@@ -60,14 +60,7 @@ int main() {
  // Now do the same for the vector double ansatz, but
  // also demonstrate the async interface
  VQE vqe_vec(ansatz_vec, H);
  auto handle = vqe_vec.execute_async(std::vector<double>{0.0});

  // Can go do other work, quantum execution is happening on
  // separate thread

  // Get the energy, this call will kick off a wait if needed
  const auto [energy_vec, params_vec] = vqe_vec.sync(handle);

  const auto [energy_vec, params_vec] = vqe_vec.execute(std::vector<double>{0.0});
  std::cout << "<H>(" << params_vec[0] << ") = " << energy_vec << "\n";

  // Now run with the mixed language kernel,
+26 −0
Original line number Diff line number Diff line
#include "qcor_hybrid.hpp"

// Define one quantum kernel that takes
// double angle parameter
__qpu__ void ansatz(qreg q, double x) {
  X(q[0]);
  Ry(q[1], x);
  CX(q[1], q[0]);
}

int main() {

  // Define the Hamiltonian using the QCOR API
  auto H = 5.907 - 2.1433 * X(0) * X(1) - 2.1433 * Y(0) * Y(1) + .21829 * Z(0) -
           6.125 * Z(1);

  // Create a VQE instance, must give it
  // the parameterized ansatz functor and Observable
  VQE vqe(ansatz, H);
  for (auto [iter, x] :
       enumerate(linspace(-constants::pi, constants::pi, 20))) {
    std::cout << iter << ", " << x << ", " << vqe({x}) << "\n";
  }

  vqe.persist_data("param_sweep_data.json");
}
 No newline at end of file
+33 −39
Original line number Diff line number Diff line
@@ -112,29 +112,13 @@ public:
  // Execute the VQE task synchronously, assumes default optimizer
  VQEResultType execute(KernelArgs... initial_params) {
    auto optimizer = qcor::createOptimizer(DEFAULT_OPTIMIZER);
    auto handle = execute_async(optimizer, initial_params...);
    return this->sync(handle);
  }

  // Execute the VQE task asynchronously, default optimizer
  Handle execute_async(KernelArgs... initial_params) {
    auto optimizer = qcor::createOptimizer(DEFAULT_OPTIMIZER);
    return execute_async(optimizer, initial_params...);
    return execute(optimizer, initial_params...);
  }

  // Execute the VQE task synchronously, use provided Optimizer
  //   template <typename... Args>
  VQEResultType execute(std::shared_ptr<Optimizer> optimizer,
                        KernelArgs... initial_params) {
    auto handle = execute_async(optimizer, initial_params...);
    return this->sync(handle);
  }

  // Execute the VQE task asynchronously, use provided Optimizer
  //   template <typename... Args>
  Handle execute_async(std::shared_ptr<Optimizer> optimizer,
                       KernelArgs... initial_params) {

    auto ansatz_casted =
        reinterpret_cast<void (*)(std::shared_ptr<CompositeInstruction>, qreg,
                                  KernelArgs...)>(ansatz_ptr);
@@ -177,15 +161,34 @@ public:
    }
    options.insert("observable", __internal__::qcor_as_shared(&observable));
    objective->set_options(options);
    return optimizer->optimize(*objective.get());
  }

    // Run TaskInitiate, kick of the VQE job asynchronously
    return qcor::taskInitiate(objective, optimizer);
  double operator()(const std::vector<double> x) {
    auto ansatz_casted =
        reinterpret_cast<void (*)(std::shared_ptr<CompositeInstruction>, qreg,
                                  KernelArgs...)>(ansatz_ptr);

    // Create the Arg Translator
    TranslationFunctor<qreg, KernelArgs...> arg_translator;
    if (translation_functor.has_value()) {
      arg_translator = std::any_cast<TranslationFunctor<qreg, KernelArgs...>>(
          translation_functor);
    } else {
      __internal__::TranslationFunctorAutoGenerator auto_gen;
      arg_translator = auto_gen(q, std::tuple<KernelArgs...>());
    }

  // Sync up the results with the host thread
  VQEResultType sync(Handle &h) {
    auto results = qcor::sync(h);
    return std::make_pair(results.opt_val, results.opt_params);
    // Get the VQE ObjectiveFunction and set the qreg
    auto objective = qcor::createObjectiveFunction(
        ansatz_casted, observable,
        std::make_shared<ArgsTranslator<qreg, KernelArgs...>>(arg_translator),
        q, x.size());

    options.insert("observable", __internal__::qcor_as_shared(&observable));
    objective->set_options(options);

    return (*objective)(x);
  }

  // Return all unique parameter sets this VQE run used
@@ -210,6 +213,11 @@ public:
    }
    return ret;
  }

  void persist_data(const std::string& filename) {
      q.write_file(filename);
  }

};

namespace __internal__ {
@@ -371,15 +379,6 @@ public:
  // initial parameters Will fail if initial_parameters.size() != n_parameters()
  QAOAResultType execute(std::shared_ptr<Optimizer> optimizer,
                       const std::vector<double> initial_parameters = {}) {
    auto handle = execute_async(optimizer, initial_parameters);
    auto results = this->sync(handle);
    return std::make_pair(results.first, results.second);
  }

  // Execute the algorithm asynchronously, provding an Optimizer and optionally
  // initial parameters Will fail if initial_parameters.size() != n_parameters()
  Handle execute_async(std::shared_ptr<Optimizer> optimizer,
                       const std::vector<double> initial_parameters = {}) {

    q = qalloc(cost.nBits());
    auto n_params = nSteps * (n_gamma() + n_beta());
@@ -422,14 +421,9 @@ public:
    objective->set_options(options);
    optimizer->appendOption("initial-parameters", init_params);

    return qcor::taskInitiate(objective, optimizer);
    return optimizer->optimize(*objective.get());// qcor::taskInitiate(objective, optimizer);
  }

  // Sync up the results with the host thread
  QAOAResultType sync(Handle &h) {
    auto results = qcor::sync(h);
    return std::make_pair(results.opt_val, results.opt_params);
  }
}; // namespace qcor

void execute_adapt(qreg q, const HeterogeneousMap &&m);
+44 −0
Original line number Diff line number Diff line
@@ -13,7 +13,20 @@ using namespace cppmicroservices;
#include "xacc_internal_compiler.hpp"
#include "xacc_service.hpp"

namespace {

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
  os << "[";
  for (int i = 0; i < v.size(); ++i) {
    os << v[i];
    if (i != v.size() - 1)
      os << ",";
  }
  os << "]";
  return os;
}
} // namespace
namespace qcor {

class VQEObjective : public ObjectiveFunction {
@@ -35,13 +48,43 @@ public:

    auto tmp_child = qalloc(qreg.size());
    auto val = vqe->execute(xacc::as_shared_ptr(tmp_child.results()), {})[0];
    double std_dev = 0.0;
    if (options.keyExists<int>("vqe-gather-statistics")) {
      std::vector<double> all_energies;
      all_energies.push_back(val);
      auto n = options.get<int>("vqe-gather-statistics");
      for (int i = 1; i < n; i++) {
        auto tmp_child = qalloc(qreg.size());
        auto local_val =
            vqe->execute(xacc::as_shared_ptr(tmp_child.results()), {})[0];
        all_energies.push_back(local_val);
      }
      auto sum = std::accumulate(all_energies.begin(), all_energies.end(), 0.);
      val = sum / all_energies.size();
      double sq_sum = std::inner_product(
          all_energies.begin(), all_energies.end(), all_energies.begin(), 0.0);
      std_dev = std::sqrt(sq_sum / all_energies.size() - val * val);
    }

    std::cout << "<H>(" << this->current_iterate_parameters << ") = " << val;
    if (std::fabs(std_dev) > 1e-12) {
      std::cout << " +- " << std_dev << "\n";
    } else {
      std::cout << std::endl;
    }
    
    // want to store parameters, have to do it here
    for (auto &child : tmp_child.results()->getChildren()) {
      child->addExtraInfo("parameters", current_iterate_parameters);
      auto tmp = current_iterate_parameters;
      tmp.push_back(val);
      child->addExtraInfo("qcor-params-energy", tmp);
      if (std::fabs(std_dev) > 1e-12) {
        child->addExtraInfo("qcor-energy-stddev", std_dev);
      }
      child->addExtraInfo("iteration", current_iteration);
    }
    current_iteration++;
    qreg.addChild(tmp_child);

    if (!dx.empty() && options.stringExists("gradient-strategy")) {
@@ -68,6 +111,7 @@ public:
  }

public:
  int current_iteration = 0;
  const std::string name() const override { return "vqe"; }
  const std::string description() const override { return ""; }
};
Loading