Commit 4b40a33c authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

bug fixes, cleanup, removed async mode from qcor hybrid since its pretty buggy

parent e8b831b5
Loading
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