List of callables as an input to the kernel raises an error
Required prerequisites
- [x] Consult the security policy. If reporting a security vulnerability, do not report the bug using this form. Use the process described in the policy to report the issue.
- [x] Make sure you've read the documentation. Your issue may be addressed there.
- [x] Search the issue tracker to verify that this hasn't already been reported. +1 or comment there if it has.
- [ ] If possible, make a PR with a failing test to give us a starting point to work on!
Describe the bug
I can use a callable as an input to the kernel, but the list of callables raises an error.
RuntimeError: kernel argument type is 'list' but argument provided is not (argument 0, value=module {
func.func @__nvqpp__mlirgen__X(%arg0: !quake.ref) attributes {"cudaq-kernel"} {
quake.x %arg0 : (!quake.ref) -> ()
return
}
}
, type=<class 'cudaq.kernel.kernel_decorator.PyKernelDecorator'>).
Steps to reproduce the bug
import cudaq
from typing import Callable
@cudaq.kernel
def X(q : cudaq.qubit):
x(q)
@cudaq.kernel
def kernel(f: list[Callable[[cudaq.qubit], None]]):
q = cudaq.qvector(2)
f[0](q[0])
f[1](q[1])
result = cudaq.sample(kernel, [X,X])
print(result)
Expected behavior
The kernel should be able to accept a list of callables.
Is this a regression? If it is, put the last known working version (or commit) here.
Not a regression
Environment
- CUDA-Q version:
- Python version:
- C++ compiler:
- Operating system:
Suggestions
No response
Related Issue : If you try to do an adjoint operation on such a callable, it gives an error. @schweitzpgi
import cudaq
from typing import Callable
@cudaq.kernel
def X(q : cudaq.qubit):
x(q)
@cudaq.kernel
def kernel(f: Callable[[cudaq.qubit], None]):
q = cudaq.qvector(2)
f(q[0])
cudaq.adjoint(f, q[1])
result = cudaq.sample(kernel, X)
Error:
error: 'quake.apply' op operand #0 must be Proxy for a C++ callable instance in cc, but got '!quake.ref'
RuntimeError: Failure while executing pass pipeline.
During handling of the above exception, another exception occurred:
RuntimeError: could not compile code for 'kernel'.
Not sure what is going on, but weirdly enough the following code works while the previous one I submitted still doesn't.
import cudaq
import numpy as np
from typing import Callable
@cudaq.kernel
def X(q : cudaq.qubit, q1 : cudaq.qubit):
x.ctrl(q, q1)
@cudaq.kernel
def CA(q : cudaq.qubit, q1 : cudaq.qubit, f: Callable[[cudaq.qubit, cudaq.qubit], None]):
f(q, q1)
@cudaq.kernel
def CA2(a : cudaq.qubit, q : cudaq.qvector, f: Callable[[cudaq.qubit, cudaq.qubit], None]):
f(a, q[0])
@cudaq.kernel
def kernel(b: np.ndarray, f: Callable[[cudaq.qubit, cudaq.qubit], None]):
q = cudaq.qvector(2)
ancilla = cudaq.qubit()
f(q[0], q[1])
CA(ancilla, q[0], f)
cudaq.adjoint(CA, ancilla, q[0], f) # Why does this work?
CA2(ancilla, q, f)
cudaq.adjoint(CA2, ancilla, q, f) # Why does this work?
bvec = np.zeros(8)
result = cudaq.sample(kernel, bvec, X)
Related issue https://github.com/NVIDIA/cuda-quantum/issues/3477
Investigating this issue.
Another weird behavior that shows up with a small modifications to the code snippet above - I am now passing two callables, f and g, although the second one doesn't get used. It hangs for a bit and then spits out the following error:
error: number of callable block arguments != number of function names provided.
error: number of callable block arguments != number of function names provided.
Segmentation fault (core dumped)
The corresponding snippet:
import cudaq
import numpy as np
from typing import Callable
@cudaq.kernel
def X(q : cudaq.qubit, q1 : cudaq.qubit):
x.ctrl(q, q1)
@cudaq.kernel
def CA(q : cudaq.qubit, q1 : cudaq.qubit, f: Callable[[cudaq.qubit, cudaq.qubit], None]):
f(q, q1)
@cudaq.kernel
def CA2(a : cudaq.qubit, q : cudaq.qvector, f: Callable[[cudaq.qubit, cudaq.qubit], None]):
f(a, q[0])
@cudaq.kernel
def kernel(b: np.ndarray, f: Callable[[cudaq.qubit, cudaq.qubit], None], g: Callable[[cudaq.qubit, cudaq.qubit], None]):
q = cudaq.qvector(2)
ancilla = cudaq.qubit()
f(q[0], q[1])
CA(ancilla, q[0], f)
cudaq.adjoint(CA, ancilla, q[0], f) # FIXME
CA2(ancilla, q, f)
cudaq.adjoint(CA2, ancilla, q, f) # FIXME
bvec = np.zeros(8)
result = cudaq.sample(kernel, bvec, X, X) # two callables, one doesn't get used inside the kernel.
Seems like we are not handling list[Callable] as a parameter to a kernel in CUDA-Q. We will need to add this feature. In the meantime, I will try to get a workaround.