4. Quantum Operators

4.1. cudaq::spin_op

CUDA Quantum provides a native spin_op data type in the cudaq namespace for the expression of quantum mechanical spin operators. These operators should provide an abstraction for a general tensor product of Pauli spin operators, and sums thereof:

\[H = \sum_{i=0}^M P_i, P_i = \prod_{j=0}^N \sigma_j^a\]

for \(a = {x,y,z}\), \(j\) the qubit index, and \(N\) the number of qubits.

Critically, the spin_op exposes common C++ operator overloads for algebraic expressions.

CUDA Quantum defines convenience functions in cudaq::spin namespace that produce the primitive X, Y, and Z Pauli operators on specified qubit indices which can subsequently be used in algebraic expressions to build up more complicated Pauli tensor products and their sums.

using namespace cudaq::spin;
auto h = 5.907 - 2.1433 * x(0) * x(1) - 2.1433 * y(0) * y(1) + \
         .21829 * z(0) - 6.125 * z(1);

The spin_op also provides a mechanism for the expression of circuit synthesis tasks within quantum kernel code. Specifically, operations that encode \(N\)thorder trotterization of exponentiated spin_op rotations, e.g. \(U = \exp(-i H t)\), where \(H\) is the provided spin_op.

The spin_op can be created within classical host code and quantum kernel code, and can also be passed by value to quantum kernel code from host code.

namespace cudaq {
  enum class pauli { I, X, Y, Z };

  class spin_op {
      using binary_symplectic_form = std::vector<std::vector<bool>>;

      spin_op(const spin_op&);
      static spin_op from_binary_symplectic(binary_symplectic_form& data,
                        std::vector<std::complex<double>>& coeffs);

      std::size_t n_qubits() const;
      std::size_t n_terms() const;
      std::complex<double> get_term_coefficient(std::size_t idx);
      std::vector<std::complex<double>> get_coefficients();
      bool is_identity();
      std::string to_string() const;

      // Extract a set of terms
      spin_op slice(std::size_t startIdx, std::size_t count);

      // Custom operations on terms and paulis
      void for_each_term(std::function<void(spin_op&)>&&);
      void for_each_pauli(std::function<void(pauli, std::size_t)>&&);

      // Common algebraic overloads
      spin_op& operator=(const spin_op&);
      spin_op& operator+=(const spin_op&);
      spin_op& operator-=(const spin_op&);
      spin_op& operator*=(const spin_op&);
      bool operator==(const spin_op&);
      spin_op& operator*=(const double);
      spin_op& operator*=(const std::complex<double>)
      // ... other algebraic overloads ...

      spin_op operator[](std::size_t);

  namespace spin {
    spin_op i(size_t);
    spin_op x(std::size_t);
    spin_op y(std::size_t);
    spin_op z(std::size_t);

The spin_op is intended only for two-level qudit (qubit) CUDA Quantum programs.