NVIDIA / cuda-quantum

C++ and Python support for the CUDA Quantum programming model for heterogeneous quantum-classical workflows
https://nvidia.github.io/cuda-quantum/
Other
488 stars 180 forks source link

[RFC] Introduce cudaq::pauli_word type to the language #1098

Closed amccaskey closed 1 month ago

amccaskey commented 8 months ago

A powerful mechanism for circuit synthesis would be to accept cudaq::spin_op as input to a quantum kernel and use that with a synthesis operation like exp_pauli. Fully supporting spin_op via the AST Bridge and MLIR is a large task. An easier stepping stone that would enable a wide range of use cases (ones we are already seeing) is to introduce a cudaq::pauli_word type. This type would model a single term in a spin_op. For example, the spin_op op = x(0) * y(1) - 2.0 * z(0) z(1) would contain 2 pauli words, specifically X0 Y1 and Z0 Z1 (I propose we ignore the coefficient as part of our cudaq::pauli_word type, coefficients can be extracted from a spin_op and passed separately as a std::vector<double>). So the type would effectively provide an opaque type that map to a ptr<i8> in the AST Bridge and be compatible with our existing ExpPauliOp.

__qpu__ void test(double theta, std::vector<cudaq::pauli_word> paulis) {
  cudaq::qvector q(2);
  for (auto &p : paulis)
    exp_pauli(theta, q, p);
}

void useTest() {
  spin_op op = ... ;
  auto words = op.to_pauli_words();
  auto results = cudaq::sample(test, M_PI_2, words);
}
kernel, thetas, paulisArg = cudaq.make_kernel(list[float], list[cudaq.pauli_word])
qubits = kernel.qalloc(2)
kernel.x(qubits[0])
kernel.for_loop(
     0, paulisArg.size(),
     lambda idx: kernel.exp_pauli(thetas[idx], qubits, paulisArg[idx]))

Note this is related to PR #1062. It seems smarter to force this type of input to be a separate type in the language rather than a catch-all const char *.

justinlietz commented 8 months ago

For example, the spin_op op = x(0) * y(1) - 2.0 * z(0) z(1) would contain 2 pauli words, specifically X0 Y1 and Z0 Z1 (I propose we ignore the coefficient as part of our cudaq::pauli_word type, coefficients can be extracted from a spin_op and passed separately as a std::vector<double>).

I think there is a lot of value in having additional pauli types. To properly model a single in a spin_op, would we support all of the math operations that can be done between two spin_op_terms?

As for naming, I think "pauli_word" is a good descriptor for the latter case where the lack of math/phase support is perhaps suggested in the name. If there is math support, then perhaps it could be called a "pauli_element" or something suggestive of the fact that these are elements of the n-qubit Pauli group with support for math/phases.

bettinaheim commented 3 months ago

RFC needs updating to capture the complete API available from both C++ and Python.

bettinaheim commented 1 month ago

Closing this as supported to the extend that it was defined here.