Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
8d323f2
initial work
awennersteen Jan 28, 2025
d95b08e
Merge pull request #1 from awennersteen/aw/initial-work
awennersteen Jan 28, 2025
f35782c
Orginazing Pasqal files (#3)
kaosmicadei Feb 6, 2025
fb77b36
Fix constant values
kaosmicadei Feb 7, 2025
451c414
Helper methods implementation (#4)
kaosmicadei Feb 14, 2025
cb78788
fix field name on payload
kaosmicadei Feb 14, 2025
734dad9
fix `createJob` path
kaosmicadei Feb 14, 2025
f88d67f
Merge branch 'main' into km/sync
kaosmicadei Feb 14, 2025
f23e891
Merge pull request #5 from awennersteen/km/sync
awennersteen Feb 14, 2025
9665a97
begin docs
awennersteen Feb 14, 2025
43049b1
Merge remote-tracking branch 'refs/remotes/origin/main'
awennersteen Feb 14, 2025
1189b09
Merge pull request #7 from awennersteen/aw/sync-upstreams
awennersteen Feb 14, 2025
48eb189
Add PasqalTester
kaosmicadei Feb 17, 2025
e320af0
[hotfix] Pasqal `constructGetJobPath`
kaosmicadei Feb 17, 2025
0e36977
Review on Pasqal files (#10)
kaosmicadei Feb 18, 2025
0b7051a
Merge pull request #6 from awennersteen/aw/docs
awennersteen Feb 18, 2025
08ff585
Merge branch 'NVIDIA:main' into main
awennersteen Feb 18, 2025
1b6df18
DCO Remediation Commit for Aleksander Wennersteen <aleksander.wenners…
awennersteen Feb 18, 2025
2c1e2b5
DCO Remediation Commit for Kaonan Micadei <k.micadei@gmail.com>
kaosmicadei Feb 18, 2025
25e1f35
DCO Remediation Commit for Kaonan Micadei <k.micadei@gmail.com>
kaosmicadei Feb 18, 2025
04efb12
DCO Remediation Commit for Kaonan Micadei <kaosmicadei@users.noreply.…
kaosmicadei Feb 18, 2025
2db5014
DCO Remediation Commit for Kaonan Micadei <k.micadei@gmail.com>
kaosmicadei Feb 18, 2025
37b0c76
Update PasqalServerHelper.cpp
kaosmicadei Feb 18, 2025
9a1f0d8
Minor edits on docs
awennersteen Feb 18, 2025
4d110be
Merge remote-tracking branch 'refs/remotes/origin/main'
awennersteen Feb 18, 2025
12c2851
[fix] Pasqal payload format
kaosmicadei Feb 19, 2025
03c9558
Fix issues preventing correct execution and update example
awennersteen Feb 24, 2025
6bb84fd
Apply basic CR
awennersteen Feb 25, 2025
6faceb9
target opt-out
kaosmicadei Feb 25, 2025
2d237d1
* Test behavior from C++ frontend when using `pasqal` target
khalatepradnya Feb 25, 2025
c915625
Fix code to use new results json structure
awennersteen Feb 26, 2025
02f8a93
Merge pull request #12 from khalatepradnya/c++_test_pasqal
awennersteen Feb 26, 2025
15a0d8b
Apply yapf formatting to Python
awennersteen Feb 26, 2025
3b0fc0c
Fix docs rendering
awennersteen Feb 26, 2025
fdcfab5
Integration test
awennersteen Feb 26, 2025
3a3dcd3
Fix integration test - missing dependency
awennersteen Feb 26, 2025
8596a75
Fix behaviour when job fails; fix constant in doc example
kaosmicadei Feb 26, 2025
c72f044
fix spell check
awennersteen Feb 26, 2025
7065bd3
* Update example to show how to target QPU
khalatepradnya Feb 26, 2025
5a06910
Merge pull request #14 from khalatepradnya/pasqal-updates
awennersteen Feb 27, 2025
0ef2db6
Update docs and remove todo
awennersteen Feb 27, 2025
a3a9b15
results now in big-endian
kaosmicadei Feb 27, 2025
84db999
Merge branch 'main' into main
khalatepradnya Feb 27, 2025
491c1bb
* Updated logo
khalatepradnya Feb 27, 2025
d4ec9f5
Merge pull request #15 from khalatepradnya/new-logo
awennersteen Feb 27, 2025
6ff4bfa
Merge branch 'main' into main
khalatepradnya Feb 27, 2025
882d7a5
Merge branch 'main' into main
khalatepradnya Feb 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/config/spelling_allowlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ OpenSUSE
Ou
POSIX
PSIRT
Pasqal
Pauli
Paulis
Photonic
Expand Down
33 changes: 32 additions & 1 deletion .github/workflows/integration_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ on:
- ionq
- iqm
- oqc
- pasqal
- quantinuum
- nvqc
- orca
Expand Down Expand Up @@ -693,7 +694,37 @@ jobs:
exit 1
fi
shell: bash


- name: Submit to Pasqal test server
if: (success() || failure()) && (inputs.target == 'pasqal' || github.event_name == 'schedule' || inputs.target == 'nightly')
run: |
echo "### Submit to Pasqal server" >> $GITHUB_STEP_SUMMARY
python3 -m pip install pasqal-cloud
export PASQAL_USERNAME='${{ secrets.PASQAL_USERNAME }}'
export PASQAL_PASSWORD='${{ secrets.PASQAL_PASSWORD }}'
export PASQAL_PROJECT_ID='${{ secrets.PASQAL_PROJECT_ID }}'
export PASQAL_MACHINE_TARGET="EMU_FREE" # Speedup queuing time
set +e # Allow script to keep going through errors
test_err_sum=0
python_tests="docs/sphinx/targets/python/pasqal.py"
for filename in $python_tests; do
[ -e "$filename" ] || echo "::error::Couldn't find file ($filename)"
python3 $filename 1> /dev/null
test_status=$?
if [ $test_status -eq 0 ]; then
echo ":white_check_mark: Successfully ran test: $filename" >> $GITHUB_STEP_SUMMARY
else
echo ":x: Test failed (failed to execute): $filename" >> $GITHUB_STEP_SUMMARY
test_err_sum=$((test_err_sum+1))
fi
done
set -e # Re-enable exit code error checking
if [ ! $test_err_sum -eq 0 ]; then
echo "::error::${test_err_sum} tests failed. See step summary for a list of failures"
exit 1
fi
shell: bash

- name: Submit to ${{ inputs.target }}
# The full set of tests used by this step is currently only supported on
# Quantinuum. The other supported tests are tested by the step above.
Expand Down
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ if (NOT DEFINED CUDAQ_ENABLE_BRAKET_BACKEND)
set(CUDAQ_ENABLE_BRAKET_BACKEND ON CACHE BOOL "Enable building AWS SDK for Amazon Braket backends.")
endif()

# Enable Pasqal target by default.
if (NOT DEFINED CUDAQ_ENABLE_PASQAL_BACKEND)
set(CUDAQ_ENABLE_PASQAL_BACKEND ON CACHE BOOL "Enable building the Pasqal target.")
endif()

# Generate a CompilationDatabase (compile_commands.json file) for our build,
# for use by clang_complete, YouCompleteMe, etc.
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
Expand Down
4 changes: 3 additions & 1 deletion docs/sphinx/api/languages/cpp_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,9 @@ Platform

.. doxygenclass:: cudaq::FermioniqBaseQPU

.. doxygenclass:: cudaq::OrcaRemoteRESTQPU
.. doxygenclass:: cudaq::OrcaRemoteRESTQPU

.. doxygenclass:: cudaq::PasqalBaseQPU

.. doxygenclass:: cudaq::QuEraBaseQPU

Expand Down
65 changes: 65 additions & 0 deletions docs/sphinx/targets/python/pasqal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import cudaq
from cudaq.operator import *

# This example illustrates how to use Pasqal's EMU_MPS emulator over Pasqal's cloud via CUDA-Q.

# To obtain the authentication token we recommend logging in
# by using Pasqal's Python SDK.
# Fill in the username and password via the environment variables.
# The password can be left empty in an interactive session to be
# prompted to enter the it securely via the command line interface.
#
# Contact Pasqal at help@pasqal.com or through https://community.pasqal.com for assistance.
#
# See our general docs https://docs.pasqal.com/cloud/set-up/
# to see how to get this setup, or the CUDA-Q documentation at
# https://nvidia.github.io/cuda-quantum/latest/using/backends/hardware/neutralatom.html#pasqal
from pasqal_cloud import SDK
import os

sdk = SDK(
username=os.environ.get("PASQAL_USERNAME"),
password=os.environ.get("PASQAL_PASSWORD", None),
)
token = sdk._client.authenticator.token_provider.get_token()

os.environ["PASQAL_AUTH_TOKEN"] = str(token)

cudaq.set_target("pasqal",
machine=os.environ.get("PASQAL_MACHINE_TARGET", "EMU_MPS"))

# ```
# cudaq.set_target("pasqal", machine="FRESNEL") ## To target QPU
# ```

# Define the 2-dimensional atom arrangement
a = 5e-6
register = [(a, 0), (2 * a, 0), (3 * a, 0)]
time_ramp = 0.000001
time_max = 0.000003
# Times for the piece-wise linear waveforms
steps = [0.0, time_ramp, time_max - time_ramp, time_max]
schedule = Schedule(steps, ["t"])
# Rabi frequencies at each step
omega_max = 1000000
delta_end = 1000000
delta_start = 0.0
omega = ScalarOperator(lambda t: omega_max if time_ramp < t < time_max else 0.0)
# Global phase at each step
phi = ScalarOperator.const(0.0)
# Global detuning at each step
delta = ScalarOperator(lambda t: delta_end
if time_ramp < t < time_max else delta_start)

async_result = evolve_async(RydbergHamiltonian(atom_sites=register,
amplitude=omega,
phase=phi,
delta_global=delta),
schedule=schedule,
shots_count=100).get()
async_result.dump()

## Sample result
# ```
# {'001': 16, '010': 23, '100': 19, '000': 42}
# ```
79 changes: 79 additions & 0 deletions docs/sphinx/using/backends/hardware/neutralatom.rst
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,85 @@ Submitting



Pasqal
++++++++++++++++

Pasqal is a quantum computing hardware company that builds quantum processors from ordered neutral atoms in 2D and 3D
arrays to bring a practical quantum advantage to its customers and address real-world problems.
The currently available Pasqal QPUs are analog quantum computers, and one, named Fresnel, is available through our cloud
portal.

In order to access Pasqal's devices you need an account for `Pasqal's cloud platform <https://portal.pasqal.cloud>`__
and an active project. Although a different interface, `Pasqal's Pulser library <https://pulser.readthedocs.io/en/latest/>`__, is a good
resource for getting started with analog neutral atom quantum computing. For support you can also use `Pasqal Community <https://community.pasqal.com/>`__.


.. _pasqal-backend:

Setting Credentials
```````````````````

An authentication token for the session must be obtained from Pasqal's cloud platform.
For example from Python one can use the `pasqal-cloud package <https://github.com/pasqal-io/pasqal-cloud>`__ as below:

.. code:: python

from pasqal_cloud import SDK
import os

sdk = SDK(
username=os.environ.get['PASQAL_USERNAME'],
password=os.environ.get('PASQAL_PASSWORD', None)
)

token = sdk._client.authenticator.token_provider.get_token()
os.environ['PASQAL_AUTH_TOKEN'] = str(token)
os.environ['PASQAL_PROJECT_ID'] = 'your project id'

Alternatively, users can set the following environment variables directly.

.. code:: bash

export PASQAL_AUTH_TOKEN=<>
export PASQAL_PROJECT_ID=<>


Submission from Python
`````````````````````````

The target to which quantum kernels are submitted
can be controlled with the ``cudaq::set_target()`` function.

.. code:: python

cudaq.set_target('pasqal')


Due to the nature of the underlying hardware, this target only supports the
``evolve`` and ``evolve_async`` APIs.
The `hamiltonian` must be an `Operator` of the type `RydbergHamiltonian`. Only
other parameters supported are `schedule` (mandatory) and `shots_count` (optional).

For example,

.. code:: python

evolution_result = evolve(RydbergHamiltonian(atom_sites=register,
amplitude=omega,
phase=phi,
delta_global=delta),
schedule=schedule)

The number of shots for a kernel execution can be set through the ``shots_count``
argument to ``evolve`` or ``evolve_async``. By default, the ``shots_count`` is
set to 100.

.. code:: python

cudaq.evolve(RydbergHamiltonian(...), schedule=s, shots_count=1000)

To see a complete example for using Pasqal's backend, take a look at our :doc:`Python examples <../../examples/hardware_providers>`.


QuEra Computing
++++++++++++++++
Expand Down
Binary file modified docs/sphinx/using/backends/qpus.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 12 additions & 1 deletion docs/sphinx/using/examples/hardware_providers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,18 @@ This experiment is performed on ORCA's backends by the code below.

.. literalinclude:: ../../targets/cpp/orca.cpp
:language: cpp


Pasqal
==================================

The following code illustrates how to run kernels on Pasqal's backends.

.. tab:: Python

.. literalinclude:: ../../targets/python/pasqal.py
:language: python


Quantinuum
==================================

Expand Down
11 changes: 6 additions & 5 deletions python/cudaq/operator/evolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
from ..kernel.kernel_builder import PyKernel, make_kernel
from ..runtime.observe import observe

analog_targets = ["pasqal", "quera"]


def _taylor_series_expm(op_matrix: NDArray[numpy.complexfloating],
order: int = 20) -> NDArray[numpy.complexfloating]:
Expand Down Expand Up @@ -210,7 +212,7 @@ def evolve_single(
collapse_operators, observables,
store_intermediate_results, integrator)

if target_name == "quera":
if target_name in analog_targets:
## TODO: Convert result from `sample_result` to `evolve_result`
return _launch_analog_hamiltonian_kernel(target_name, hamiltonian,
schedule, shots_count)
Expand Down Expand Up @@ -351,11 +353,10 @@ def evolve(
during evolution.
"""
target_name = cudaq_runtime.get_target().name

if not isinstance(schedule, Schedule):
raise ValueError(
f"Invalid argument `schedule` for target {target_name}.")
if target_name == "quera":
if target_name in analog_targets:
if not isinstance(hamiltonian, RydbergHamiltonian):
raise ValueError(
f"Invalid argument `hamiltonian` for target {target_name}. Must be `RydbergHamiltonian` operator."
Expand Down Expand Up @@ -432,7 +433,7 @@ def evolve_single_async(
collapse_operators, observables, store_intermediate_results,
integrator))

if target_name == "quera":
if target_name in analog_targets:
return _launch_analog_hamiltonian_kernel(target_name, hamiltonian,
schedule, shots_count, True)

Expand Down Expand Up @@ -548,7 +549,7 @@ def evolve_async(
if not isinstance(schedule, Schedule):
raise ValueError(
f"Invalid argument `schedule` for target {target_name}.")
if target_name == "quera":
if target_name in analog_targets:
if not isinstance(hamiltonian, RydbergHamiltonian):
raise ValueError(
f"Invalid argument `hamiltonian` for target {target_name}. Must be `RydbergHamiltonian` operator."
Expand Down
4 changes: 2 additions & 2 deletions python/cudaq/operator/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1272,8 +1272,8 @@ def __rsub__(self: ScalarOperator, other: Any) -> ScalarOperator:

class RydbergHamiltonian(OperatorSum):
"""
Representation for the time-dependent Hamiltonian which is simulated by
QuEra's Aquila machine.
Representation for the time-dependent Hamiltonian which is simulated by
analog neutral-atom machines such as QuEra's Aquila and Pasqal's Fresnel.
Ref: https://docs.aws.amazon.com/braket/latest/developerguide/braket-quera-submitting-analog-program-aquila.html#braket-quera-ahs-program-schema
"""

Expand Down
2 changes: 2 additions & 0 deletions python/extension/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ declare_mlir_python_extension(CUDAQuantumPythonSources.Extension
../../runtime/cudaq/platform/orca/OrcaQPU.cpp
../../runtime/cudaq/platform/orca/OrcaRemoteRESTQPU.cpp
../../runtime/cudaq/platform/orca/OrcaServerHelper.cpp
../../runtime/cudaq/platform/pasqal/PasqalRemoteRESTQPU.cpp
../../runtime/cudaq/platform/pasqal/PasqalServerHelper.cpp

EMBED_CAPI_LINK_LIBS
CUDAQuantumMLIRCAPI
Expand Down
72 changes: 72 additions & 0 deletions python/tests/backends/test_Pasqal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# ============================================================================ #
# Copyright (c) 2022 - 2025 NVIDIA Corporation & Affiliates. #
# All rights reserved. #
# #
# This source code and the accompanying materials are made available under #
# the terms of the Apache License 2.0 which accompanies this distribution. #
# ============================================================================ #

import cudaq
from cudaq.operator import *
import json
import os
import pytest

skipIfPasqalNotInstalled = pytest.mark.skipif(
not (cudaq.has_target("pasqal")),
reason='Could not find `pasqal` in installation')


@pytest.fixture(scope="session", autouse=True)
def do_something():
# NOTE: Credentials can be set with environment variables
cudaq.set_target("pasqal")
yield "Running the tests."
cudaq.reset_target()


@skipIfPasqalNotInstalled
def test_JSON_payload():
input = {
"setup": {
"ahs_register": {
"sites": [[0, 0], [0, 0.000004], [0.000004, 0]],
"filling": [1, 1, 1]
}
},
"hamiltonian": {
"drivingFields": [{
"amplitude": {
"time_series": {
"values": [0, 15700000, 15700000, 0],
"times": [0, 0.000001, 0.000002, 0.000003]
},
"pattern": "uniform"
},
"phase": {
"time_series": {
"values": [0, 0],
"times": [0, 0.000003]
},
"pattern": "uniform"
},
"detuning": {
"time_series": {
"values": [-54000000, 54000000],
"times": [0, 0.000003]
},
"pattern": "uniform"
}
}],
"localDetuning": []
}
}
# NOTE: For internal testing only, not user-level API; this does not return results
cudaq.cudaq_runtime.pyAltLaunchAnalogKernel("__analog_hamiltonian_kernel__",
json.dumps(input))


# leave for gdb debugging
if __name__ == "__main__":
loc = os.path.abspath(__file__)
pytest.main([loc, "-rP"])
Loading
Loading