[RFC] Unitary Synthesis
khalatepradnya opened this issue · 4 comments
khalatepradnya commented
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)
User API
- Python
import cudaq
custom_h = cudaq.register_operation(1. / np.sqrt(2.) * np.array([[1, 1], [1, -1]]))
custom_x = cudaq.register_operation(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_op("custom_h",
{{M_SQRT1_2, M_SQRT1_2}, {M_SQRT1_2, -M_SQRT1_2}});
cudaq_register_op("custom_x", {{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
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](https://private-user-images.githubusercontent.com/148914294/324040932-d85a93b0-df46-4d9b-add0-72ee32014265.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTQ3NjM0NTAsIm5iZiI6MTcxNDc2MzE1MCwicGF0aCI6Ii8xNDg5MTQyOTQvMzI0MDQwOTMyLWQ4NWE5M2IwLWRmNDYtNGQ5Yi1hZGQwLTcyZWUzMjAxNDI2NS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwNTAzJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDUwM1QxOTA1NTBaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1iYzQ4ODE2YmZiNjhkNDIxYjhmYzg4Mzc3MWFkNDJjM2U0OThiZGE1OWJlZDMwNDM5OTE0MWM2ZmZjN2FhMTMzJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.0YmpF8ERB8Nqcjpz689ptqFyNZ0FDrG9BCq5UCsUtGw)
- 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
- Support in simulation for Python -
- Kernel mode
- Builder mode
- State vector simulators
- Tensornet simulators
- Support in simulation for C++
- Library mode
- MLIR mode
- Add generic synthesis for emulation
- Error handling: Gracefully handle user errors, feature constraints and runtime errors
- Comprehensive documentation and useful example(s)
- Support synthesis per hardware backend