Skip to content

Commit 86aaeb2

Browse files
committed
Merge branch 'main' of https://github.com/NVIDIA/cuda-quantum into dynamics_cpp_operators
Signed-off-by: Bettina Heim <[email protected]>
2 parents f7b8b84 + 3e931d8 commit 86aaeb2

File tree

121 files changed

+2398
-713
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+2398
-713
lines changed

.github/workflows/clean_up.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151

5252
steps:
5353
- run: |
54-
gh release list -L 100 -R ${{ github.repository }} > rels.txt
54+
gh release list -L 1000 -R ${{ github.repository }} > rels.txt
5555
while read rel _; do
5656
isDraft=`gh release view $rel -R ${{ github.repository }} --json isDraft --jq '.isDraft'`
5757
isPrerelease=`gh release view $rel -R ${{ github.repository }} --json isPrerelease --jq '.isPrerelease'`

.github/workflows/docker_images.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,11 @@ jobs:
707707
fi
708708
709709
docker run --rm -dit --network host --name cuda-quantum-dev $cudaqdev_image
710+
# Unfortunately, we need to install cuquantum for docs generation to work properly,
711+
# since using mock imports in the autodocs configuration doesn't work properly.
712+
# See also https://github.com/sphinx-doc/sphinx/issues/11211.
713+
docker exec cuda-quantum-dev bash -c "python3 -m pip install cuquantum-python-cu12~=24.11"
714+
710715
(docker exec cuda-quantum-dev bash -c "export $docs_version && bash scripts/build_docs.sh" && built=true) || built=false
711716
if $built; then docker cp cuda-quantum-dev:"/usr/local/cudaq/docs/." docs; \
712717
else docker cp cuda-quantum-dev:"/workspaces/cuda-quantum/build/." /tmp/build; fi

.github/workflows/python_metapackages.yml

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ jobs:
7777
7878
echo "Creating README.md for cuda-quantum package"
7979
echo "# Welcome to the CUDA-Q Python API" > README.md
80-
echo "This package is deprecated and new versions are published under the name `cudaq` instead." >> README.md
80+
echo "This package is deprecated and new versions are published under the name \`cudaq\` instead." >> README.md
8181
echo "For more information, please see [CUDA-Q on PyPI](https://pypi.org/project/cudaq)." >> README.md
8282
8383
echo "Building cuda-quantum metapackage ..."
@@ -195,8 +195,6 @@ jobs:
195195
fi
196196
197197
- name: Test installation error
198-
# FIXME: We actually don't give a proper install error if there are conflicting packages on the system...
199-
if: matrix.cuda_version == ''
200198
run: |
201199
python=python${{ matrix.python_version }}
202200
$python -m pip install pypiserver
@@ -211,11 +209,13 @@ jobs:
211209
set -e && check_package=cuda-quantum
212210
;;
213211
12.*)
212+
test_conflicting=cuda-quantum-cu11
214213
$python -m pip install cuda-quantum-cu11==${{ inputs.cudaq_version }} \
215214
--extra-index-url http://localhost:8080
216215
set +e # continue on error
217216
$python -m pip install cudaq==${{ inputs.cudaq_version }} -v \
218-
--extra-index-url http://localhost:8080
217+
--extra-index-url http://localhost:8080 \
218+
2>&1 | tee /tmp/install.out
219219
set -e && check_package=cudaq
220220
;;
221221
*)
@@ -225,17 +225,37 @@ jobs:
225225
set -e
226226
if [ -z "$($python -m pip list | grep cuda-quantum)" ]; then
227227
# if we don't have a 0.8.0 version for this python version, test other conflict
228+
test_conflicting=cuda-quantum-cu12
228229
$python -m pip install cuda-quantum-cu12==${{ inputs.cudaq_version }} \
229230
--extra-index-url http://localhost:8080
231+
else
232+
test_conflicting=cuda-quantum
230233
fi
231234
set +e # continue on error
232235
$python -m pip install cudaq==${{ inputs.cudaq_version }} -v \
233-
--extra-index-url http://localhost:8080
236+
--extra-index-url http://localhost:8080 \
237+
2>&1 | tee /tmp/install.out
234238
set -e && check_package=cudaq
235239
;;
236240
esac
237241
238-
if [ -n "$($python -m pip list | grep ${check_package})" ]; then
242+
# The autodetection will fail if the runner does not have a GPU.
243+
# In that case, we will only check if the install failed, if the
244+
# package we want to test the conflict detection for is not the
245+
# default package that is installed when there is no GPU.
246+
if [ -f /tmp/install.out ] && [ -z "$(cat /tmp/install.out | grep -o 'Autodetection succeeded')" ]; then
247+
# Autodetection failed - a default choice of the binary distribution will be installed.
248+
echo "::warning::Autodetection to determine cudaq binary distribution failed."
249+
# Take the first Identified best package because the logs print multiple lines.
250+
# They should all be the same, if they differ in the build environment then there is probably issues.
251+
installed_default=$(cat /tmp/install.out | sed -nE 's/.*Identified (\S*) as the best package.*/\1/p' | head -n 1)
252+
echo "::warning::The installed default is ${installed_default}, the potential conflicting package is ${test_conflicting}"
253+
if [ "$installed_default" == "$test_conflicting" ]; then
254+
check_package=none
255+
fi
256+
fi
257+
258+
if [ "$check_package" != "none" ] && [ -n "$($python -m pip list | grep ${check_package})" ]; then
239259
echo "::error file=python_metapackages.yml::Unexpected installation of ${check_package} package."
240260
exit 1
241261
fi

docker/build/devdeps.ext.Dockerfile

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends gnupg \
5959

6060
ARG PMI_INSTALL_PREFIX=/usr/local/pmi
6161
ENV PMI_INSTALL_PREFIX="$PMI_INSTALL_PREFIX"
62-
ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PMIX_INSTALL_PREFIX/lib"
62+
ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PMI_INSTALL_PREFIX/lib"
6363
COPY --from=ompibuild "$PMI_INSTALL_PREFIX" "$PMI_INSTALL_PREFIX"
6464

6565
# Copy over GDRCOPY and install runtime dependencies.
@@ -161,7 +161,10 @@ ENV CUDA_PATH="$CUDA_INSTALL_PREFIX"
161161
ENV PATH="${CUDA_INSTALL_PREFIX}/lib64/:${CUDA_INSTALL_PREFIX}/bin:${PATH}"
162162

163163
# Install cuQuantum dependencies, including cuTensor.
164-
RUN python3 -m pip install cuquantum-python-cu$(echo $CUDA_VERSION | cut -d . -f1)~=24.11 && \
164+
RUN apt-get update && apt-get install -y --no-install-recommends \
165+
python3 python3-pip && \
166+
apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* && \
167+
python3 -m pip install cuquantum-python-cu$(echo $CUDA_VERSION | cut -d . -f1)~=24.11 && \
165168
if [ "$(python3 --version | grep -o [0-9\.]* | cut -d . -f -2)" != "3.10" ]; then \
166169
echo "expecting Python version 3.10"; \
167170
fi
@@ -173,7 +176,7 @@ ENV CUQUANTUM_PATH="$CUQUANTUM_INSTALL_PREFIX"
173176
ENV LD_LIBRARY_PATH="$CUQUANTUM_INSTALL_PREFIX/lib:$LD_LIBRARY_PATH"
174177
ENV CPATH="$CUQUANTUM_INSTALL_PREFIX/include:$CPATH"
175178

176-
ARG CUTENSOR_INSTALL_PREFIX=/usr/local/lib/python3.10/dist-packages/cutensor/
179+
ARG CUTENSOR_INSTALL_PREFIX=/usr/local/lib/python3.10/dist-packages/cutensor
177180
ENV CUTENSOR_INSTALL_PREFIX="$CUTENSOR_INSTALL_PREFIX"
178181
ENV CUTENSOR_ROOT="$CUTENSOR_INSTALL_PREFIX"
179182
ENV LD_LIBRARY_PATH="$CUTENSOR_INSTALL_PREFIX/lib:$LD_LIBRARY_PATH"

docker/release/cudaq.Dockerfile

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ FROM $cudaqdev_image AS cudaqbuild
3232
# access to the environment variables, so that the hardcoded paths in this file don't need to
3333
# match the paths in the dev image.
3434
RUN mkdir /usr/local/cudaq_assets && cd /usr/local/cudaq_assets && \
35-
mkdir -p llvm/bin && mkdir -p llvm/lib && mkdir cuquantum && \
35+
mkdir -p llvm/bin && mkdir -p llvm/lib && \
3636
mv "$LLVM_INSTALL_PREFIX/bin/"clang* "/usr/local/cudaq_assets/llvm/bin/" && rm -rf "/usr/local/cudaq_assets/llvm/bin/"clang-format* && \
3737
mv "$LLVM_INSTALL_PREFIX/lib/"clang* "/usr/local/cudaq_assets/llvm/lib/" && \
3838
mv "$LLVM_INSTALL_PREFIX/bin/llc" "/usr/local/cudaq_assets/llvm/bin/llc" && \
@@ -56,10 +56,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
5656
# Install CUDA-Q runtime dependencies.
5757

5858
RUN apt-get update && apt-get install -y --no-install-recommends \
59-
python3 python3-pip libstdc++-12-dev \
59+
libstdc++-12-dev python3 python3-pip \
6060
&& apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* \
61-
&& python3 -m pip install --no-cache-dir \
62-
numpy scipy cuquantum-python-cu$(echo ${CUDA_VERSION:-12} | cut -d . -f1)~=24.11 \
61+
&& python3 -m pip install --no-cache-dir numpy scipy \
6362
&& ln -s /bin/python3 /bin/python
6463
RUN apt-get update && apt-get install -y --no-install-recommends gcc g++ python3-dev \
6564
# Ref: https://github.com/qutip/qutip/issues/2412

docs/sphinx/conf.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ def setup(app):
179179

180180
autosummary_generate = True
181181

182+
# This is unfortunately not sufficient for docs generation, due to the use of Union type;
183+
# see also https://github.com/sphinx-doc/sphinx/issues/11211.
184+
# autodoc_mock_imports = ['cuquantum', 'cupy']
185+
182186
intersphinx_mapping = {
183187
'python': ('https://docs.python.org/3/', None),
184188
'numpy': ('https://numpy.org/doc/stable/', None),

docs/sphinx/targets/cpp/braket.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Compile and run with:
2+
// ```
3+
// nvq++ --target braket braket.cpp -o out.x && ./out.x
4+
// ```
5+
// This will submit the job to the Amazon Braket state vector simulator
6+
// (default). Alternatively, users can choose any of the available devices by
7+
// specifying its `ARN` with the `--braket-machine`, e.g.,
8+
// ```
9+
// nvq++ --target braket --braket-machine \
10+
// "arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet" braket.cpp -o out.x
11+
// ./out.x
12+
// ```
13+
// Assumes a valid set of credentials have been set prior to execution.
14+
15+
#include <cudaq.h>
16+
#include <fstream>
17+
18+
// Define a simple quantum kernel to execute on Amazon Braket.
19+
struct ghz {
20+
// Maximally entangled state between 5 qubits.
21+
auto operator()() __qpu__ {
22+
cudaq::qvector q(5);
23+
h(q[0]);
24+
for (int i = 0; i < 4; i++) {
25+
x<cudaq::ctrl>(q[i], q[i + 1]);
26+
}
27+
auto result = mz(q);
28+
}
29+
};
30+
31+
int main() {
32+
// Submit asynchronously (e.g., continue executing
33+
// code in the file until the job has been returned).
34+
auto future = cudaq::sample_async(ghz{});
35+
// ... classical code to execute in the meantime ...
36+
37+
// Get the results of the read in future.
38+
auto async_counts = future.get();
39+
async_counts.dump();
40+
41+
// OR: Submit synchronously (e.g., wait for the job
42+
// result to be returned before proceeding).
43+
auto counts = cudaq::sample(ghz{});
44+
counts.dump();
45+
}

docs/sphinx/targets/python/braket.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import cudaq
2+
3+
# NOTE: Amazon Braket credentials must be set before running this program.
4+
# Amazon Braket costs apply.
5+
cudaq.set_target("braket")
6+
7+
# The default device is SV1, state vector simulator. Users may choose any of
8+
# the available devices by supplying its `ARN` with the `machine` parameter.
9+
# For example,
10+
# ```
11+
# cudaq.set_target("braket", machine="arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet")
12+
# ```
13+
14+
15+
# Create the kernel we'd like to execute
16+
@cudaq.kernel
17+
def kernel():
18+
qvector = cudaq.qvector(2)
19+
h(qvector[0])
20+
x.ctrl(qvector[0], qvector[1])
21+
mz(qvector)
22+
23+
24+
# Execute and print out the results.
25+
26+
# Option A:
27+
# By using the asynchronous `cudaq.sample_async`, the remaining
28+
# classical code will be executed while the job is being handled
29+
# by Amazon Braket.
30+
async_results = cudaq.sample_async(kernel)
31+
# ... more classical code to run ...
32+
33+
async_counts = async_results.get()
34+
print(async_counts)
35+
36+
# Option B:
37+
# By using the synchronous `cudaq.sample`, the execution of
38+
# any remaining classical code in the file will occur only
39+
# after the job has been returned from Amazon Braket.
40+
counts = cudaq.sample(kernel)
41+
print(counts)

docs/sphinx/using/backends/backends.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ CUDA-Q Backends
1212

1313
**The following is a comprehensive list of the available targets in CUDA-Q:**
1414

15+
* :ref:`braket <braket-backend>`
1516
* :ref:`density-matrix-cpu <default-simulator>`
1617
* :ref:`fermioniq <fermioniq-backend>`
1718
* :ref:`ionq <ionq-backend>`

docs/sphinx/using/backends/hardware.rst

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,114 @@ CUDA-Q supports submission to a set of hardware providers.
55
To submit to a hardware backend, you need an account with the respective provider.
66

77

8+
Amazon Braket
9+
==================================
10+
11+
.. _braket-backend:
12+
13+
`Amazon Braket <https://aws.amazon.com/braket/>`__ is a fully managed AWS
14+
service which provides Jupyter notebook environments, high-performance quantum
15+
circuit simulators, and secure, on-demand access to various quantum computers.
16+
To get started users must enable Amazon Braket in their AWS account by following
17+
`these instructions <https://docs.aws.amazon.com/braket/latest/developerguide/braket-enable-overview.html>`__.
18+
To learn more about Amazon Braket, you can view the `Amazon Braket Documentation <https://docs.aws.amazon.com/braket/>`__
19+
and `Amazon Braket Examples <https://github.com/amazon-braket/amazon-braket-examples>`__.
20+
A list of available devices and regions can be found `here <https://docs.aws.amazon.com/braket/latest/developerguide/braket-devices.html>`__.
21+
22+
Users can run CUDA-Q programs on Amazon Braket with `Hybrid Job <https://docs.aws.amazon.com/braket/latest/developerguide/braket-what-is-hybrid-job.html>`__.
23+
See `this guide <https://docs.aws.amazon.com/braket/latest/developerguide/braket-jobs-first.html>`__ to get started.
24+
25+
Setting Credentials
26+
```````````````````
27+
28+
After enabling Amazon Braket in AWS, set credentials using any of the documented `methods <https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html>`__.
29+
One of the simplest ways is to use `AWS CLI <https://aws.amazon.com/cli/>`__.
30+
31+
.. code:: bash
32+
33+
aws configure
34+
35+
Alternatively, users can set the following environment variables.
36+
37+
.. code:: bash
38+
39+
export AWS_DEFAULT_REGION="<region>"
40+
export AWS_ACCESS_KEY_ID="<key_id>"
41+
export AWS_SECRET_ACCESS_KEY="<access_key>"
42+
export AWS_SESSION_TOKEN="<token>"
43+
44+
Submission from C++
45+
`````````````````````````
46+
47+
To target quantum kernel code for execution in Amazon Braket,
48+
pass the flag ``--target braket`` to the ``nvq++`` compiler.
49+
By default jobs are submitted to the state vector simulator, `SV1`.
50+
51+
.. code:: bash
52+
53+
nvq++ --target braket src.cpp
54+
55+
56+
To execute your kernels on different device, pass the ``--braket-machine`` flag to the ``nvq++`` compiler
57+
to specify which machine to submit quantum kernels to:
58+
59+
.. code:: bash
60+
61+
nvq++ --target braket --braket-machine "arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet" src.cpp ...
62+
63+
where ``arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet`` refers to IQM Garnet QPU.
64+
65+
To emulate the device locally, without submitting through the cloud,
66+
you can also pass the ``--emulate`` flag to ``nvq++``.
67+
68+
.. code:: bash
69+
70+
nvq++ --emulate --target braket src.cpp
71+
72+
To see a complete example for using Amazon Braket backends, take a look at our :doc:`C++ examples <../examples/examples>`.
73+
74+
Submission from Python
75+
`````````````````````````
76+
77+
The target to which quantum kernels are submitted
78+
can be controlled with the ``cudaq::set_target()`` function.
79+
80+
.. code:: python
81+
82+
cudaq.set_target("braket")
83+
84+
By default, jobs are submitted to the state vector simulator, `SV1`.
85+
86+
To specify which Amazon Braket device to use, set the :code:`machine` parameter.
87+
88+
.. code:: python
89+
90+
device_arn = "arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet"
91+
cudaq.set_target("braket", machine=device_arn)
92+
93+
where ``arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet`` refers to IQM Garnet QPU.
94+
95+
To emulate the device locally, without submitting through the cloud,
96+
you can also set the ``emulate`` flag to ``True``.
97+
98+
.. code:: python
99+
100+
cudaq.set_target("braket", emulate=True)
101+
102+
The number of shots for a kernel execution can be set through the ``shots_count``
103+
argument to ``cudaq.sample``. By default, the ``shots_count`` is set to 1000.
104+
105+
.. code:: python
106+
107+
cudaq.sample(kernel, shots_count=100)
108+
109+
To see a complete example for using Amazon Braket backends, take a look at our :doc:`Python examples <../examples/examples>`.
110+
111+
.. note::
112+
113+
The ``cudaq.observe`` API is not yet supported on the `braket` target.
114+
115+
8116
IonQ
9117
==================================
10118

@@ -314,7 +422,7 @@ Setting Credentials
314422
`````````````````````````
315423

316424
In order to use the OQC devices you will need to register.
317-
Registration is achieved by contacting [email protected]
425+
Registration is achieved by contacting `[email protected]`.
318426

319427
Once registered you will be able to authenticate with your ``email`` and ``password``
320428

0 commit comments

Comments
 (0)