Unverified Commit d5da017d authored by Mccaskey, Alex's avatar Mccaskey, Alex Committed by GitHub
Browse files

Merge pull request #72 from tnguyen-ornl/tnguyen/qsim-adapt

Added Adapt workflow to QSim and general clean-up of QSim
parents bd8b3029 78c8826d
Loading
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -21,3 +21,8 @@ add_test(NAME qrt_ftqc_steane_qec_std_lib COMMAND ${CMAKE_BINARY_DIR}/qcor -c -q
add_test(NAME qsim_vqe COMMAND ${CMAKE_BINARY_DIR}/qcor ${CMAKE_CURRENT_SOURCE_DIR}/qsim/VqeWithAnsatzCircuit.cpp)
add_test(NAME qsim_trotter COMMAND ${CMAKE_BINARY_DIR}/qcor ${CMAKE_CURRENT_SOURCE_DIR}/qsim/TrotterTdWorkflow.cpp)
add_test(NAME qsim_iqpe_vqe COMMAND ${CMAKE_BINARY_DIR}/qcor ${CMAKE_CURRENT_SOURCE_DIR}/qsim/IterativeQpeVqe.cpp)
add_test(NAME qsim_adapt_vqe COMMAND ${CMAKE_BINARY_DIR}/qcor ${CMAKE_CURRENT_SOURCE_DIR}/qsim/AdaptVqeWorkflow.cpp)
add_test(NAME qsim_qaoa COMMAND ${CMAKE_BINARY_DIR}/qcor ${CMAKE_CURRENT_SOURCE_DIR}/qsim/QaoaWorkflow.cpp)
add_test(NAME qsim_qite COMMAND ${CMAKE_BINARY_DIR}/qcor ${CMAKE_CURRENT_SOURCE_DIR}/qsim/QiteWorkflow.cpp)
add_test(NAME qsim_heisenberg COMMAND ${CMAKE_BINARY_DIR}/qcor ${CMAKE_CURRENT_SOURCE_DIR}/qsim/TdWorkflowHeisenbergModel.cpp)
add_test(NAME qsim_verified_qpe COMMAND ${CMAKE_BINARY_DIR}/qcor ${CMAKE_CURRENT_SOURCE_DIR}/qsim/VerifiedQuantumPhaseEstimation.cpp)
+48 −0
Original line number Diff line number Diff line
#include "qcor_qsim.hpp"

// Demonstrate qsim's Adapt-VQE workflow
/// $ qcor -qpu qpp AdaptVqeWorkflow.cpp
/// $ ./a.out

int main(int argc, char **argv) {
  const auto str = std::string(
      "(-0.165606823582,-0)  1^ 2^ 1 2 + (0.120200490713,0)  1^ 0^ 0 1 + "
      "(-0.0454063328691,-0)  0^ 3^ 1 2 + (0.168335986252,0)  2^ 0^ 0 2 + "
      "(0.0454063328691,0)  1^ 2^ 3 0 + (0.168335986252,0)  0^ 2^ 2 0 + "
      "(0.165606823582,0)  0^ 3^ 3 0 + (-0.0454063328691,-0)  3^ 0^ 2 1 + "
      "(-0.0454063328691,-0)  1^ 3^ 0 2 + (-0.0454063328691,-0)  3^ 1^ 2 0 + "
      "(0.165606823582,0)  1^ 2^ 2 1 + (-0.165606823582,-0)  0^ 3^ 0 3 + "
      "(-0.479677813134,-0)  3^ 3 + (-0.0454063328691,-0)  1^ 2^ 0 3 + "
      "(-0.174072892497,-0)  1^ 3^ 1 3 + (-0.0454063328691,-0)  0^ 2^ 1 3 + "
      "(0.120200490713,0)  0^ 1^ 1 0 + (0.0454063328691,0)  0^ 2^ 3 1 + "
      "(0.174072892497,0)  1^ 3^ 3 1 + (0.165606823582,0)  2^ 1^ 1 2 + "
      "(-0.0454063328691,-0)  2^ 1^ 3 0 + (-0.120200490713,-0)  2^ 3^ 2 3 + "
      "(0.120200490713,0)  2^ 3^ 3 2 + (-0.168335986252,-0)  0^ 2^ 0 2 + "
      "(0.120200490713,0)  3^ 2^ 2 3 + (-0.120200490713,-0)  3^ 2^ 3 2 + "
      "(0.0454063328691,0)  1^ 3^ 2 0 + (-1.2488468038,-0)  0^ 0 + "
      "(0.0454063328691,0)  3^ 1^ 0 2 + (-0.168335986252,-0)  2^ 0^ 2 0 + "
      "(0.165606823582,0)  3^ 0^ 0 3 + (-0.0454063328691,-0)  2^ 0^ 3 1 + "
      "(0.0454063328691,0)  2^ 0^ 1 3 + (-1.2488468038,-0)  2^ 2 + "
      "(0.0454063328691,0)  2^ 1^ 0 3 + (0.174072892497,0)  3^ 1^ 1 3 + "
      "(-0.479677813134,-0)  1^ 1 + (-0.174072892497,-0)  3^ 1^ 3 1 + "
      "(0.0454063328691,0)  3^ 0^ 1 2 + (-0.165606823582,-0)  3^ 0^ 3 0 + "
      "(0.0454063328691,0)  0^ 3^ 2 1 + (-0.165606823582,-0)  2^ 1^ 2 1 + "
      "(-0.120200490713,-0)  0^ 1^ 0 1 + (-0.120200490713,-0)  1^ 0^ 1 0 + "
      "(0.7080240981,0)");

  FermionOperator H_vqe;
  H_vqe.fromString(str);
  auto problemModel = qsim::ModelBuilder::createModel(&H_vqe);
  auto optimizer = createOptimizer("nlopt", {{"nlopt-optimizer", "l-bfgs"}});
  const int nElectrons = 2;
  const auto pool_vqe = "qubit-pool";
  auto workflow = qsim::getWorkflow("adapt", {{"optimizer", optimizer},
                                              {"pool", pool_vqe},
                                              {"n-electrons", nElectrons}});
  auto result = workflow->execute(problemModel);
  std::cout << "Final energy: " << result.get<double>("energy") << "\n";
  auto final_ansatz =
      result.getPointerLike<xacc::CompositeInstruction>("circuit");
  std::cout << "HOWDY: \n" << final_ansatz->toString() << "\n";
  return 0;
}
 No newline at end of file
+76 −0
Original line number Diff line number Diff line
#include "qcor_qsim.hpp"

// Simulate dynamics of a quantum quench of
// a 1D antiferromagnetic Heisenberg model.

// Compile and run with:
/// $ qcor -qpu qsim QuantumQuenchSimulation.cpp
/// $ ./a.out
int main(int argc, char **argv) {
  // Handle input parameters:
  // --n-spins : number of spins/qubits (default = 7)
  // --g: g parameter - ZZ coupling strength (default = 0.0)
  // --dt: Trotter dt (default = 0.05)
  // --steps: number of steps (defalt = 100)

  // Process the input arguments
  std::vector<std::string> arguments(argv + 1, argv + argc);
  int n_spins = 7;
  double g = 0.0;
  double dt = 0.05;
  int n_steps = 100;

  for (int i = 0; i < arguments.size(); i++) {
    if (arguments[i] == "--n-spins") {
      n_spins = std::stoi(arguments[i + 1]);
    }
    if (arguments[i] == "--g") {
      g = std::stod(arguments[i + 1]);
    }
    if (arguments[i] == "--dt") {
      dt = std::stod(arguments[i + 1]);
    }
    if (arguments[i] == "--steps") {
      n_steps = std::stoi(arguments[i + 1]);
    }
  }

  std::cout << "Running QSim for a quenching model with " << n_spins
            << " spins and g = " << g << "\n";
  std::cout << "dt " << dt << "; number of steps = " << n_steps << "\n";
  using ModelType = qcor::qsim::ModelBuilder::ModelType;
  // Initial spin state: Neel state
  std::vector<int> initial_spins;
  for (int i = 0; i < n_spins; ++i) {
    // Alternating up/down spins
    initial_spins.emplace_back(i % 2);
  }

  auto problemModel = qsim::ModelBuilder::createModel(
      ModelType::Heisenberg, {{"Jx", 1.0},
                              {"Jy", 1.0},
                              // Jz == g parameter
                              {"Jz", g},
                              // No external field
                              {"h_ext", 0.0},
                              {"ext_dir", "X"},
                              {"num_spins", n_spins},
                              {"initial_spins", initial_spins},
                              {"observable", "staggered_magnetization"}});
  // Workflow parameters:
  auto workflow =
      qsim::getWorkflow("td-evolution", {{"dt", dt}, {"steps", n_steps}});

  // Result should contain the observable expectation value along Trotter steps.
  auto result = workflow->execute(problemModel);
  // Get the observable values (staggered magnetization)
  const auto obsVals = result.get<std::vector<double>>("exp-vals");

  // Print out for debugging:
  std::cout << "<Staggered Magnetization> = \n";
  for (const auto &val : obsVals) {
    std::cout << val << "\n";
  }

  return 0;
}
+43 −5
Original line number Diff line number Diff line
@@ -50,12 +50,50 @@ ModelBuilder::createModel(ModelType type, const HeterogeneousMap &params) {
    }

    QuantumSimulationModel model;
    // Observable = average magnetization

    // Handle custom observable:
    qcor::Observable *model_observable = nullptr;
    // Get QCOR Pauli Op first (if any)
    if (params.keyExists<qcor::PauliOperator>("observable")) {
      static auto cached_pauli = params.get<qcor::PauliOperator>("observable");
      model_observable = &cached_pauli;
    }
    // Generic qcor::Observable
    else if (params.pointerLikeExists<qcor::Observable>("observable")) {
      model_observable = params.getPointerLike<qcor::Observable>("observable");
    }
    else {
      const std::vector<std::string> SUPPORTED_OBS{"average_magnetization",
                                                   "staggered_magnetization"};
      std::string observable_type = "average_magnetization";
      if (params.stringExists("observable")) {
        observable_type = params.getString("observable");
      }

      if (!xacc::container::contains(SUPPORTED_OBS, observable_type)) {
        qcor::error("Unknown observable type: " + observable_type);
      }

      auto observable = new qcor::PauliOperator;
      if (observable_type == "average_magnetization") {
        for (int i = 0; i < hs_model->num_spins; ++i) {
          (*observable) += ((1.0 / hs_model->num_spins) * Z(i));
        }
    model.observable = observable;
      }
      else if (observable_type == "staggered_magnetization") {
        double coeff = 1.0;
        for (int i = 0; i < hs_model->num_spins; ++i) {
          (*observable) += ((coeff / hs_model->num_spins) * Z(i));
          // Alternate the sign
          coeff = -coeff;
        }
      }

      model_observable = observable;
    }

    assert(model_observable);
    model.observable = model_observable;
    qsim::TdObservable H = [&](double t) {
      qcor::PauliOperator tdOp;
      for (int i = 0; i < hs_model->num_spins - 1; ++i) {
+3 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#include "workflow/qite.hpp"
#include "workflow/time_dependent.hpp"
#include "workflow/vqe.hpp"
#include "workflow/adapt.hpp"

namespace qcor {
namespace qsim {
@@ -48,6 +49,8 @@ public:
        std::make_shared<qsim::QiteWorkflow>());
    context.RegisterService<qsim::QuantumSimulationWorkflow>(
        std::make_shared<qsim::IterativeQpeWorkflow>());
    context.RegisterService<qsim::QuantumSimulationWorkflow>(
        std::make_shared<qsim::AdaptVqeWorkflow>());
    // Cost evaluators
    context.RegisterService<qsim::CostFunctionEvaluator>(
        std::make_shared<qsim::PartialTomoObjFuncEval>());
Loading