Commit 2dc99590 authored by Nguyen, Thien Minh's avatar Nguyen, Thien Minh
Browse files

Fixed a few missing ArQTiC params and added a Python example



Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent 3fc68e50
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ int main(int argc, char **argv) {
  // *steps
  // 20
  auto workflow = qsim::getWorkflow(
      "td-evolution", {{"method", "trotter"}, {"dt", 3.0}, {"steps", 20}});
      "td-evolution", {{"dt", 3.0}, {"steps", 20}});

  // Result should contain the observable expectation value along Trotter steps.
  auto result = workflow->execute(problemModel);
+39 −27
Original line number Diff line number Diff line
@@ -39,9 +39,12 @@ ModelBuilder::createModel(Observable *obs, const HeterogeneousMap &params) {
QuantumSimulationModel
ModelBuilder::createModel(ModelType type, const HeterogeneousMap &params) {
  if (type == ModelType::Heisenberg) {
    HeisenbergModel hs_model;
    hs_model.fromDict(params);
    if (!hs_model.validateModel()) {
    // Static internal HeisenbergModel struct
    // (keep alive to form time-depenedent Hamiltonian operator)
    static std::unique_ptr<HeisenbergModel> hs_model;
    hs_model = std::make_unique<HeisenbergModel>();
    hs_model->fromDict(params);
    if (!hs_model->validateModel()) {
      qcor::error(
          "Failed to validate the input parameters for the Heisenberg model.");
    }
@@ -49,38 +52,41 @@ ModelBuilder::createModel(ModelType type, const HeterogeneousMap &params) {
    QuantumSimulationModel model;
    // Observable = average magnetization
    auto observable = new qcor::PauliOperator;
    for (int i = 0; i < hs_model.num_spins; ++i) {
      (*observable) += ((1.0/hs_model.num_spins) * Z(i));
    for (int i = 0; i < hs_model->num_spins; ++i) {
      (*observable) += ((1.0/hs_model->num_spins) * Z(i));
    }
    model.observable = observable;
    qsim::TdObservable H = [&](double t) {
      qcor::PauliOperator tdOp;
      for (int i = 0; i < hs_model.num_spins - 1; ++i) {
        if (hs_model.Jx != 0.0) {
          tdOp += (hs_model.Jx * (X(i) * X(i + 1)));
      for (int i = 0; i < hs_model->num_spins - 1; ++i) {
        if (hs_model->Jx != 0.0) {
          tdOp += ((hs_model->Jx / hs_model->H_BAR) * (X(i) * X(i + 1)));
        }
        if (hs_model.Jy != 0.0) {
          tdOp += (hs_model.Jy * (Y(i) * Y(i + 1)));
        if (hs_model->Jy != 0.0) {
          tdOp += ((hs_model->Jy / hs_model->H_BAR) * (Y(i) * Y(i + 1)));
        }
        if (hs_model.Jz != 0.0) {
          tdOp += (hs_model.Jz * (Z(i) * Z(i + 1)));
        if (hs_model->Jz != 0.0) {
          tdOp += ((hs_model->Jz / hs_model->H_BAR) * (Z(i) * Z(i + 1)));
        }
      }

      std::function<double(double)> time_dep_func;
      if (hs_model.time_func) {
        time_dep_func = hs_model.time_func;
      if (hs_model->time_func) {
        time_dep_func = hs_model->time_func;
      } else {
        time_dep_func = [&](double time) { return std::cos(hs_model.freq * time); };
      }
      if (hs_model.h_ext != 0.0) {
        for (int i = 0; i < hs_model.num_spins; ++i) {
          if (hs_model.ext_dir == "X") {
            tdOp += (hs_model.h_ext * time_dep_func(t) * X(i));
          } else if (hs_model.ext_dir == "Y") {
            tdOp += (hs_model.h_ext * time_dep_func(t) * Y(i));
        time_dep_func = [&](double time) { return std::cos(hs_model->freq * time); };
      }
      if (hs_model->h_ext != 0.0) {
        for (int i = 0; i < hs_model->num_spins; ++i) {
          if (hs_model->ext_dir == "X") {
            tdOp +=
                ((hs_model->h_ext / hs_model->H_BAR) * time_dep_func(t) * X(i));
          } else if (hs_model->ext_dir == "Y") {
            tdOp +=
                ((hs_model->h_ext / hs_model->H_BAR) * time_dep_func(t) * Y(i));
          } else {
            tdOp += (hs_model.h_ext * time_dep_func(t) * Z(i));
            tdOp +=
                ((hs_model->h_ext / hs_model->H_BAR) * time_dep_func(t) * Z(i));
          }
        }
      }
@@ -90,12 +96,12 @@ ModelBuilder::createModel(ModelType type, const HeterogeneousMap &params) {
    
    model.hamiltonian = H;
    // Non-zero initial spin state:
    if (std::find(hs_model.initial_spins.begin(), hs_model.initial_spins.end(),
                  1) != hs_model.initial_spins.end()) {
    if (std::find(hs_model->initial_spins.begin(), hs_model->initial_spins.end(),
                  1) != hs_model->initial_spins.end()) {
      auto initialSpinPrep = qcor::__internal__::create_composite("InitialSpin");
      auto provider = qcor::__internal__::get_provider();
      for (int i = 0; i < hs_model.initial_spins.size(); ++i) {
        if (hs_model.initial_spins[i] == 1) {
      for (int i = 0; i < hs_model->initial_spins.size(); ++i) {
        if (hs_model->initial_spins[i] == 1) {
          initialSpinPrep->addInstruction(provider->createInstruction("X", i));
        }
      }
@@ -147,14 +153,20 @@ void ModelBuilder::HeisenbergModel::fromDict(const HeterogeneousMap &params) {
    }
  };

  // Handle exact types (int, double)
  getKeyIfExists(Jx, "Jx");
  getKeyIfExists(Jy, "Jy");
  getKeyIfExists(Jz, "Jz");
  getKeyIfExists(ext_dir, "ext_dir");
  getKeyIfExists(h_ext, "h_ext");
  getKeyIfExists(H_BAR, "H_BAR");
  getKeyIfExists(num_spins, "num_spins");
  getKeyIfExists(initial_spins, "initial_spins");
  getKeyIfExists(time_func, "time_func");
  getKeyIfExists(freq, "freq");
  // Handle string-like
  if (params.stringExists("ext_dir")) {
    ext_dir = params.getString("ext_dir");
  }
}
} // namespace qsim
} // namespace qcor
 No newline at end of file
+3 −1
Original line number Diff line number Diff line
@@ -91,9 +91,11 @@ public:
    double Jy = 0.0;
    double Jz = 0.0;
    double h_ext = 0.0;
    // Support for H_BAR normalization
    double H_BAR = 1.0;
    // "X", "Y", or "Z"
    std::string ext_dir = "Z";
    size_t num_spins = 2;
    int num_spins = 2;
    std::vector<int> initial_spins;
    // Time-dependent freq.
    // Default to using the cosine function.
+29 −0
Original line number Diff line number Diff line
import sys, os
from pathlib import Path
sys.path.insert(1, str(Path.home()) + "/.xacc")

from qcor import *
import numpy as np
import matplotlib.pyplot as plt

# Demonstrate Heisenberg model (ArQTiC format) input
problemModel = qsim.ModelBuilder.createModel(ModelType.Heisenberg, {'Jz': 0.01183898,
                                                       'h_ext': 0.01183898,
                                                       'freq': 0.0048,
                                                       'ext_dir': 'X',
                                                       'num_spins': 3})
# Run TD workflow:
workflow = qsim.getWorkflow(
      'td-evolution', {'dt': 3.0, 'steps': 20})
result = workflow.execute(problemModel)

# Plot the result:
t = np.linspace(0, 60, 21)
y = result["exp-vals"]
axes = plt.axes()
axes.plot(t, y)
axes.set_xlim([0,60])
axes.set_ylim([0,1])
# Save the plot to a file:
os.chdir(os.path.dirname(os.path.abspath(__file__)))
plt.savefig("avg_magnetization_plot.pdf")  
 No newline at end of file
+12 −2
Original line number Diff line number Diff line
@@ -732,8 +732,18 @@ PYBIND11_MODULE(_pyqcor, m) {
            [](qcor::PauliOperator &obs) {
              return qcor::qsim::ModelBuilder::createModel(obs);
            },
            "");

            "")
        .def(
            "createModel",
            [](qcor::qsim::ModelBuilder::ModelType type,
               PyHeterogeneousMap &params) {
              auto nativeHetMap = heterogeneousMapConvert(params);
              return qcor::qsim::ModelBuilder::createModel(type, nativeHetMap);
            },
            "Create a model of a supported type.");
    py::enum_<qcor::qsim::ModelBuilder::ModelType>(m, "ModelType")
        .value("Heisenberg", qcor::qsim::ModelBuilder::ModelType::Heisenberg)
        .export_values();
    // CostFunctionEvaluator bindings
    py::class_<qcor::qsim::CostFunctionEvaluator,
               std::shared_ptr<qcor::qsim::CostFunctionEvaluator>,