cuda-quantum icon indicating copy to clipboard operation
cuda-quantum copied to clipboard

[RFC] Unitary Synthesis

Open khalatepradnya opened this issue 10 months ago • 7 comments

Describe the feature

Problem

Given a user provided arbitrary quantum unitary, synthesize it into a sequence of quantum gates.

Expectations

  • User provides an arbitrary unitary matrix as a custom quantum operation.
  • The custom operation can be used as a regular CUDA-Q supported quantum operation.
    • Q: Broadcast (same operation on multiple qubits): Out of scope
  • The allowed set of quantum gates for synthesis depends on the backend target.
    • Q: Allow user to specify set of allowed gates: Out of scope
  • CUDA-Q throws error if a unitary cannot be synthesized (reasonably).
    • 'reasonably' to account for time limit (timeout), gate count limit (upper threshold), and how close the synthesized "circuit" is to the input unitary (tolerance)
  • Parameterized custom operations will be covered in a follow-up RFC.

User API

  • Python
import cudaq 

cudaq.register_operation("custom_h", 1. / np.sqrt(2.) *  np.array([[1, 1], [1, -1]])) 
cudaq.register_operation("custom_x", np.array([[0, 1], [1, 0]])) 

@cudaq.kernel 
def bell(): 
  qubits = cudaq.qvector(2) 
  custom_h(qubits[0]) 
  custom_x.ctrl(qubits[0], qubits[1]) 

counts = cudaq.sample(bell) 
counts.dump()

  • C++
// Macro to specify the custom unitary operation
cudaq_register_operation(custom_h, 1, 0,
                         (std::vector<std::vector<std::complex<double>>>{
                             {M_SQRT1_2, M_SQRT1_2}, {M_SQRT1_2, -M_SQRT1_2}}));
cudaq_register_operation(
    custom_x, 1, 0, (std::vector<std::vector<std::complex<double>>>{{0, 1}, {1, 0}}));

void custom_operation() __qpu__ {
  cudaq::qvector qubits(2);
  custom_h(qubits[0]);
  custom_x.ctrl(qubits[0], qubits[1]);
}

int main() {
  auto result = cudaq::sample(custom_operation);
  std::cout << result.most_probable() << '\n';
  return 0;
}
  • The user must provide valid unitary matrix (CUDA-Q will not check / enforce this requirement)
  • Ordering: The user provided matrix must be in row-major format
  • Endianness: The user provided matrix is interpreted as Big-endian (often followed by Physics textbooks).

Constraints

  • Size of unitary matrix: limit to 8 qubits, (2^8 = 256), 256 x 256
  • The custom operation must be defined outside of a quantum kernel. (for e.g. call to register_operation cannot be inside a function decorated with @cudaq.kernel)
  • The tolerance for the synthesized circuit and the gate count limit will be default values determined by CUDA-Q
  • The custom operation definition is restricted to qubit (cudaq::qudit<2>).

Workflow

image
  • In simulation, no synthesis will happen.
  • Compiler will automatically synthesize the matrix when targeting hardware.
  • Explicit synthesis mechanism (API or command-line argument) - Out of scope for the first iteration
  • NVQC target behaves same as when running locally

Work items / TO-DOs

  • [x] Support in simulation for Python -
    • [x] Kernel mode
    • [x] Builder mode
    • [x] State vector simulators
    • [x] Tensornet simulators
  • [x] Support in simulation for C++
    • [x] Library mode
    • [x] MLIR mode
  • [x] Add generic synthesis for emulation
  • [x] Error handling: Gracefully handle user errors, feature constraints and runtime errors
  • [ ] Support synthesis per hardware backend
  • [ ] ~~Comprehensive documentation and useful example(s)~~: Covered in issue #2002

khalatepradnya avatar Apr 04 '24 16:04 khalatepradnya