How to add multi-controlled gates when using `cudaq.make_kernel()` approach
Closed this issue · 2 comments
ACE07-Sev commented
Greetings there,
Hope all are well. I am trying to wrap cuda-quantum
in my package, and I would like to follow a qiskit
UI. I saw the closest to that UI is to use cudaq.make_kernel()
and add gates as methods. However, I am having some difficulty doing this for multi-controlled gates.
Here is a toy class example to demonstrate the issue:
import cudaq
class CUDA:
def __init__(self,
num_qubits: int) -> None:
self.num_qubits = num_qubits
self.circuit = cudaq.make_kernel()
self.qr = self.circuit.qalloc(self.num_qubits)
def X(self,
qubit_index: int) -> None:
self.circuit.x(self.qr[qubit_index])
def H(self,
qubit_index: int) -> None:
self.circuit.h(self.qr[qubit_index])
def CX(self,
control_index: int,
target_index: int) -> None:
# Create a Controlled-X gate
target_kernel, qubit = cudaq.make_kernel(cudaq.qubit)
target_kernel.x(qubit)
# Apply the CX gate to the circuit at the specified control and target qubits
self.circuit.control(target_kernel, self.qr[control_index], self.qr[target_index])
def CCX(self,
control_index1: int,
control_index2: int,
target_index: int) -> None:
# Create a Controlled-X gate
target_kernel, qubit = cudaq.make_kernel(cudaq.qubit)
target_kernel.x(qubit)
# Apply the CX gate to the circuit at the specified control and target qubits
self.circuit.control(target_kernel, [self.qr[control_index1], self.qr[control_index2]], self.qr[target_index])
def draw(self) -> None:
print(cudaq.draw(self.circuit))
qc = CUDA(3)
qc.CCX(0, 1, 2)
qc.draw()
And the error I am getting is
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[11], [line 39](vscode-notebook-cell:?execution_count=11&line=39)
[36](vscode-notebook-cell:?execution_count=11&line=36) print(cudaq.draw(self.circuit))
[38](vscode-notebook-cell:?execution_count=11&line=38) qc = CUDA(3)
---> [39](vscode-notebook-cell:?execution_count=11&line=39) qc.CCX(0, 1, 2)
[40](vscode-notebook-cell:?execution_count=11&line=40) qc.draw()
Cell In[11], [line 33](vscode-notebook-cell:?execution_count=11&line=33)
[31](vscode-notebook-cell:?execution_count=11&line=31) target_kernel.x(qubit)
[32](vscode-notebook-cell:?execution_count=11&line=32) # Apply the CX gate to the circuit at the specified control and target qubits
---> [33](vscode-notebook-cell:?execution_count=11&line=33) self.circuit.control(target_kernel, [self.qr[control_index1], self.qr[control_index2]], self.qr[target_index])
File /mnt/c/Users/A.C.EA/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/cudaq/kernel/kernel_builder.py:871, in PyKernel.control(self, target, control, *target_arguments)
[837](https://vscode-remote+wsl-002bubuntu.vscode-resource.vscode-cdn.net/mnt/c/Users/A.C.EA/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/cudaq/kernel/kernel_builder.py:837) def control(self, target, control, *target_arguments):
[838](https://vscode-remote+wsl-002bubuntu.vscode-resource.vscode-cdn.net/mnt/c/Users/A.C.EA/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/cudaq/kernel/kernel_builder.py:838) """
[839](https://vscode-remote+wsl-002bubuntu.vscode-resource.vscode-cdn.net/mnt/c/Users/A.C.EA/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/cudaq/kernel/kernel_builder.py:839) Apply the `target` kernel as a controlled operation in-place to
[840](https://vscode-remote+wsl-002bubuntu.vscode-resource.vscode-cdn.net/mnt/c/Users/A.C.EA/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/cudaq/kernel/kernel_builder.py:840) `self`.Uses the provided `control` as control qubit/s for the operation.
(...)
[869](https://vscode-remote+wsl-002bubuntu.vscode-resource.vscode-cdn.net/mnt/c/Users/A.C.EA/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/cudaq/kernel/kernel_builder.py:869) ```
[870](https://vscode-remote+wsl-002bubuntu.vscode-resource.vscode-cdn.net/mnt/c/Users/A.C.EA/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/cudaq/kernel/kernel_builder.py:870) """
--> [871](https://vscode-remote+wsl-002bubuntu.vscode-resource.vscode-cdn.net/mnt/c/Users/A.C.EA/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/cudaq/kernel/kernel_builder.py:871) self.__applyControlOrAdjoint(target, False, [control.mlirValue],
[872](https://vscode-remote+wsl-002bubuntu.vscode-resource.vscode-cdn.net/mnt/c/Users/A.C.EA/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/cudaq/kernel/kernel_builder.py:872) *target_arguments)
[873](https://vscode-remote+wsl-002bubuntu.vscode-resource.vscode-cdn.net/mnt/c/Users/A.C.EA/Documents/GitHub/QICKIT/.venv/lib/python3.11/site-packages/cudaq/kernel/kernel_builder.py:873) return
AttributeError: 'list' object has no attribute 'mlirValue'
I am actively going through the docs and notebooks you have provided, but I'd appreciate your kind feedback on the best way of doing this as well.
1tnguyen commented
Hi @ACE07-Sev,
Looking at your example, I think you can achieve it with:
import cudaq
class CUDA:
def __init__(self,
num_qubits: int) -> None:
self.num_qubits = num_qubits
self.circuit = cudaq.make_kernel()
self.qr = self.circuit.qalloc(self.num_qubits)
def X(self,
qubit_index: int) -> None:
self.circuit.x(self.qr[qubit_index])
def H(self,
qubit_index: int) -> None:
self.circuit.h(self.qr[qubit_index])
def CX(self,
control_index: int,
target_index: int) -> None:
self.circuit.cx(self.qr[control_index], self.qr[target_index])
def CCX(self,
control_index1: int,
control_index2: int,
target_index: int) -> None:
self.circuit.cx([self.qr[control_index1], self.qr[control_index2]], self.qr[target_index])
def draw(self) -> None:
print(cudaq.draw(self.circuit))
qc = CUDA(3)
qc.H(1)
qc.CX(1, 2)
qc.CCX(0, 1, 2)
qc.draw()
ACE07-Sev commented
Ooh I see, thank you very much!