Commit 5362c511 authored by Nguyen, Thien Minh's avatar Nguyen, Thien Minh
Browse files

Work on Heisenberd model input



Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent 98e11c60
Loading
Loading
Loading
Loading
+79 −0
Original line number Diff line number Diff line
@@ -36,6 +36,66 @@ ModelBuilder::createModel(Observable *obs, const HeterogeneousMap &params) {
  return model;
}

QuantumSimulationModel
ModelBuilder::createModel(ModelType type, const HeterogeneousMap &params) {
  if (type == ModelType::Heisenberg) {
    HeisenbergModel hs_model;
    hs_model.fromDict(params);
    if (!hs_model.validateModel()) {
      qcor::error(
          "Failed to validate the input parameters for the Heisenberg model.");
    }

    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));
    }
    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)));
        }
        if (hs_model.Jy != 0.0) {
          tdOp += (hs_model.Jy * (Y(i) * Y(i + 1)));
        }
        if (hs_model.Jz != 0.0) {
          tdOp += (hs_model.Jz * (Z(i) * Z(i + 1)));
        }
      }

      std::function<double(double)> time_dep_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));
          } else {
            tdOp += (hs_model.h_ext * time_dep_func(t) * Z(i));
          }
        }
      }

      return tdOp;
    };
    
    model.hamiltonian = H;
    return model;
  } else {
    qcor::error("Unknown model type.");
    __builtin_unreachable();
  }
}

QuantumSimulationModel
ModelBuilder::createModel(const std::string &format, const std::string &data,
                          const HeterogeneousMap &params) {
@@ -64,5 +124,24 @@ getObjEvaluator(Observable *observable, const std::string &name,
  // ERROR: unknown CostFunctionEvaluator or invalid initialization options.
  return nullptr;
}

void ModelBuilder::HeisenbergModel::fromDict(const HeterogeneousMap &params) {
  const auto getKeyIfExists = [&params](auto &modelVar,
                                        const std::string &keyName) {
    using ValType = typename std::remove_reference_t<decltype(modelVar)>;
    if (params.keyExists<ValType>(keyName)) {
      modelVar = params.get<ValType>(keyName);
    }
  };

  getKeyIfExists(Jx, "Jx");
  getKeyIfExists(Jy, "Jy");
  getKeyIfExists(Jz, "Jz");
  getKeyIfExists(ext_dir, "ext_dir");
  getKeyIfExists(num_spins, "num_spins");
  getKeyIfExists(initial_spins, "initial_spins");
  getKeyIfExists(time_func, "time_func");
  getKeyIfExists(freq, "freq");
}
} // namespace qsim
} // namespace qcor
 No newline at end of file
+31 −1
Original line number Diff line number Diff line
@@ -85,6 +85,33 @@ struct QuantumSimulationModel {
// Create a model which capture the problem description.
class ModelBuilder {
public:
  // Generic Heisenberg model
  struct HeisenbergModel {
    double Jx = 0.0;
    double Jy = 0.0;
    double Jz = 0.0;
    double h_ext = 0.0;
    // "X", "Y", or "Z"
    std::string ext_dir = "Z";
    size_t num_spins = 2;
    std::vector<int> initial_spins;
    // Time-dependent freq.
    // Default to using the cosine function.
    double freq = 0.0;
    // User-provided custom time-dependent function:
    std::function<double(double)> time_func;
    // Allows a simple Pythonic kwarg-style initialization.
    // i.e. all params have preset defaults, only update those that are
    // specified.
    void fromDict(const HeterogeneousMap &params);

    bool validateModel() const {
      const bool ext_dir_valid = (ext_dir == "X" || ext_dir == "Y" || ext_dir == "Z");
      const bool initial_spins_valid = (initial_spins.empty() || (initial_spins.size() == num_spins));
      return ext_dir_valid && initial_spins_valid;
    }
  };

  // ======== Direct model builder ==============
  // Strongly-typed parameters/argument.
  // Build a simple Hamiltonian-based model: static Hamiltonian which is also
@@ -121,7 +148,10 @@ public:
  static QuantumSimulationModel createModel(const std::string &format,
                                           const std::string &data,
                                           const HeterogeneousMap &params = {});

  // Predefined model type that we support intrinsically.
  enum class ModelType { Heisenberg };
  static QuantumSimulationModel createModel(ModelType type,
                                           const HeterogeneousMap &params);
  // ========== QuantumSimulationModel with a fixed (pre-defined) ansatz ========
  // The ansatz is provided as a QCOR kernel.
  template <typename... Args>