Skip to content

Commit

Permalink
[python] qvector init from lists and arrays (#1688)
Browse files Browse the repository at this point in the history
* Add support for initialization of qvector from lists

* Fix formatting changes

* Support nd.array creation with dtypes and creating qvector from it

* temp

* Add automatic conversion to the simulation precision data type

* Use simluation dtype for alloca operation, add length checking for scalar lists

* Support creating nd arrays and initializing vectors. Add a vector copy if necessary

* Fixed spelling

* Remove dictionary.dic

* Support cudaq.amplitudes inside kernels

* Fixed test failures

* Updated test

* Fixed more failing tests

* Remove creating qvector of const length to be handled later

* Make vectors in test normalized
  • Loading branch information
annagrin authored May 20, 2024
1 parent e0a2e98 commit 5d0ec7b
Show file tree
Hide file tree
Showing 7 changed files with 982 additions and 42 deletions.
2 changes: 1 addition & 1 deletion python/cudaq/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def complex():
target = get_target()
precision = target.get_precision()
if precision == cudaq_runtime.SimulationPrecision.fp64:
return complex
return numpy.complex128
return numpy.complex64


Expand Down
5 changes: 3 additions & 2 deletions python/cudaq/kernel/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,9 @@ def visit_FunctionDef(self, node):
raise RuntimeError(
'cudaq.kernel functions must have argument type annotations.'
)
if isinstance(annotation,
ast.Subscript) and annotation.value.id == 'Callable':
if isinstance(annotation, ast.Subscript) and hasattr(
annotation.value,
"id") and annotation.value.id == 'Callable':
if not hasattr(annotation, 'slice'):
raise RuntimeError(
'Callable type must have signature specified.')
Expand Down
282 changes: 257 additions & 25 deletions python/cudaq/kernel/ast_bridge.py

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions python/cudaq/kernel/kernel_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def __processArgType(self, ty):
"""
if ty in [cudaq_runtime.qvector, cudaq_runtime.qubit]:
return ty, None
if get_origin(ty) == list or isinstance(ty(), list):
if get_origin(ty) == list or isinstance(ty, list):
if '[' in str(ty) and ']' in str(ty):
allowedTypeMap = {
'int': int,
Expand Down Expand Up @@ -685,8 +685,10 @@ def qalloc(self, initializer=None):
self.ctx,
cc.StdvecType.getElementType(
initializer.mlirValue.type))
initials = cc.StdvecDataOp(ptrTy, initializer.mlirValue)
quake.InitializeStateOp(veqTy, qubits, initials)
initials = cc.StdvecDataOp(ptrTy,
initializer.mlirValue).result
qubits = quake.InitializeStateOp(veqTy, qubits,
initials).result
return self.__createQuakeValue(qubits)

# If no initializer, create a single qubit
Expand Down
4 changes: 2 additions & 2 deletions python/cudaq/kernel/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@


class Color:
YELLOW = '\033[93m'
RED = '\033[91m'
BOLD = '\033[1m'
END = '\033[0m'
Expand Down Expand Up @@ -92,7 +93,7 @@ def emitFatalErrorOverride(msg):
return cc.CharspanType.get(ctx)

if annotation.value.id in ['numpy', 'np']:
if annotation.attr == 'ndarray':
if annotation.attr in ['array', 'ndarray']:
return cc.StdvecType.get(ctx, F64Type.get())
if annotation.attr == 'complex128':
return ComplexType.get(F64Type.get())
Expand Down Expand Up @@ -176,7 +177,6 @@ def emitFatalErrorOverride(msg):


def mlirTypeFromPyType(argType, ctx, **kwargs):

if argType == int:
return IntegerType.get_signless(64, ctx)
if argType in [float, np.float64]:
Expand Down
52 changes: 43 additions & 9 deletions python/tests/builder/test_kernel_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -877,10 +877,11 @@ def test_recursive_calls():

print(kernel3)


skipIfNvidiaFP64NotInstalled = pytest.mark.skipif(
not (cudaq.num_available_gpus() > 0 and cudaq.has_target('nvidia-fp64')),
reason='Could not find nvidia-fp64 in installation')
not (cudaq.num_available_gpus() > 0 and cudaq.has_target('nvidia-fp64')),
reason='Could not find nvidia-fp64 in installation')


@skipIfNvidiaFP64NotInstalled
def test_from_state0():
Expand Down Expand Up @@ -944,10 +945,12 @@ def test_from_state0():

cudaq.reset_target()


skipIfNvidiaNotInstalled = pytest.mark.skipif(
not (cudaq.num_available_gpus() > 0 and cudaq.has_target('nvidia')),
reason='Could not find nvidia in installation')

not (cudaq.num_available_gpus() > 0 and cudaq.has_target('nvidia')),
reason='Could not find nvidia in installation')


@skipIfNvidiaNotInstalled
def test_from_state1():
cudaq.set_target('nvidia')
Expand All @@ -969,8 +972,7 @@ def test_from_state1():

# Regardless of the target precision, use
# cudaq.complex() or cudaq.amplitudes()
state = np.array([.70710678, 0., 0., 0.70710678],
dtype=cudaq.complex())
state = np.array([.70710678, 0., 0., 0.70710678], dtype=cudaq.complex())
kernel2 = cudaq.make_kernel()
qubits = kernel2.qalloc(state)
counts = cudaq.sample(kernel2)
Expand All @@ -986,7 +988,7 @@ def test_from_state1():
assert '11' in counts
assert '00' in counts

state = cudaq.amplitudes(np.array([.5]*4))
state = cudaq.amplitudes(np.array([.5] * 4))
kernel2 = cudaq.make_kernel()
qubits = kernel2.qalloc(state)
counts = cudaq.sample(kernel2)
Expand Down Expand Up @@ -1358,6 +1360,38 @@ def test_u3_ctrl():
assert ('11' in counts)


@skipIfNvidiaFP64NotInstalled
def test_builder_rotate_state():
cudaq.reset_target()
cudaq.set_target('nvidia-fp64')

c = [0., 0., 0., 1.]

# Our kernel will start with 2 qubits in `11`, then
# rotate each qubit back to `0` before applying a
# Hadamard gate.
kernel, state = cudaq.make_kernel(list[complex])
q = kernel.qalloc(state)

# Can now operate on the qvector as usual:
# Rotate state of the front qubit 180 degrees along X.
kernel.x(q[0])
# Rotate state of the back qubit 180 degrees along Y.
kernel.y(q[1])
# Put qubits into superposition state.
kernel.h(q)

# Measure.
kernel.mz(q)

counts = cudaq.sample(kernel, c)
print(counts)
assert '11' in counts
assert '00' in counts
assert '01' in counts
assert '10' in counts


# leave for gdb debugging
if __name__ == "__main__":
loc = os.path.abspath(__file__)
Expand Down
Loading

0 comments on commit 5d0ec7b

Please sign in to comment.