Skip to content

Commit 95bb111

Browse files
Docs preview for PR #2691.
1 parent 680dbe1 commit 95bb111

File tree

17 files changed

+884
-64
lines changed

17 files changed

+884
-64
lines changed

pr-2691/_sources/using/backends/hardware/neutralatom.rst.txt

+24-5
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,11 @@ The currently available Pasqal QPUs are analog quantum computers, and one, named
139139
portal.
140140

141141
In order to access Pasqal's devices you need an account for `Pasqal's cloud platform <https://portal.pasqal.cloud>`__
142-
and an active project. Although a different interface, `Pasqal's Pulser library <https://pulser.readthedocs.io/en/latest/>`__, is a good
143-
resource for getting started with analog neutral atom quantum computing. For support you can also use `Pasqal Community <https://community.pasqal.com/>`__.
142+
and an active project. Please see our `cloud documentation <https://docs.pasqal.cloud/cloud/>`__ for more details if needed.
143+
144+
Although a different SDK, `Pasqal's Pulser library <https://pulser.readthedocs.io/en/latest/>`__, is a good
145+
resource for getting started with analog neutral atom quantum computing.
146+
For support you can also join the `Pasqal Community <https://community.pasqal.com/>`__.
144147

145148

146149
.. _pasqal-backend:
@@ -161,7 +164,8 @@ For example from Python one can use the `pasqal-cloud package <https://github.co
161164
password=os.environ.get('PASQAL_PASSWORD', None)
162165
)
163166
164-
token = sdk._client.authenticator.token_provider.get_token()
167+
token = sdk.user_token()
168+
165169
os.environ['PASQAL_AUTH_TOKEN'] = str(token)
166170
os.environ['PASQAL_PROJECT_ID'] = 'your project id'
167171
@@ -184,10 +188,25 @@ can be controlled with the ``cudaq::set_target()`` function.
184188
cudaq.set_target('pasqal')
185189
186190
191+
This accepts an optional argument, ``machine``, which is used in the cloud platform to
192+
select the corresponding Pasqal QPU or emulator to execute on.
193+
See the `Pasqal cloud portal <https://portal.pasqal.cloud/>`__ for an up to date list.
194+
The default value is ``EMU_MPS`` which is an open-source tensor network emulator based on the
195+
Matrix Product State formalism running in Pasqal's cloud platform. You can see the
196+
documentation for the publicly accessible emulator `here <https://pasqal-io.github.io/emulators/latest/emu_mps/>`__.
197+
198+
To target the QPU use the FRESNEL machine name. Note that there are restrictions
199+
regarding the values of the pulses as well as the register layout. We invite you to
200+
consult our `documentation <https://docs.pasqal.com/cloud/fresnel-job>`__. Note that
201+
the CUDA-Q integration currently only works with `arbitrary layouts <https://docs.pasqal.com/cloud/fresnel-job/#arbitrary-layouts>`__
202+
which are implemented with automatic calibration for less than 30 qubits. For jobs
203+
larger than 30 qubits please use the `atom_sites` to define the layout, and use the
204+
`atom_filling` to select sites as filled or not filled in order to define the register.
205+
187206
Due to the nature of the underlying hardware, this target only supports the
188207
``evolve`` and ``evolve_async`` APIs.
189-
The `hamiltonian` must be an `Operator` of the type `RydbergHamiltonian`. Only
190-
other parameters supported are `schedule` (mandatory) and `shots_count` (optional).
208+
The `hamiltonian` must be an `Operator` of the type `RydbergHamiltonian`. The only
209+
other supported parameters are `schedule` (mandatory) and `shots_count` (optional).
191210

192211
For example,
193212

pr-2691/applications/python/adapt_qaoa.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ <h1>ADAPT-QAOA algorithm<a class="headerlink" href="#ADAPT-QAOA-algorithm" title
783783
parameter</p>
784784
<p>3- Optimize all parameters currently in the Ansatz <span class="math notranslate nohighlight">\(\beta_m, \gamma_m = 1, 2, ...k\)</span> such that <span class="math notranslate nohighlight">\(\braket{\psi (k)|H_C|\psi(k)}\)</span> is minimized, and return to the second step.</p>
785785
<p>Below is a schematic representation of the ADAPT-QAOA algorithm explained above.</p>
786-
<div><p><img alt="0843aea15ee44e7dab227e95b2287b01" class="no-scaled-link" src="../../_images/adapt-qaoa.png" style="width: 600px;" /></p>
786+
<div><p><img alt="ce457d496ff64a2fb2eda01f62666ddb" class="no-scaled-link" src="../../_images/adapt-qaoa.png" style="width: 600px;" /></p>
787787
</div><div class="nbinput nblast docutils container">
788788
<div class="prompt highlight-none notranslate"><div class="highlight"><pre><span></span>[ ]:
789789
</pre></div>

pr-2691/applications/python/deutschs_algorithm.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ <h2>XOR <span class="math notranslate nohighlight">\(\oplus\)</span><a class="he
840840
</section>
841841
<section id="Quantum-oracles">
842842
<h2>Quantum oracles<a class="headerlink" href="#Quantum-oracles" title="Permalink to this heading"></a></h2>
843-
<p><img alt="763d7815f173412799295a8433b41c16" class="no-scaled-link" src="../../_images/oracle.png" style="width: 300px; height: 150px;" /></p>
843+
<p><img alt="06d9075282e14060805653effb7f0b37" class="no-scaled-link" src="../../_images/oracle.png" style="width: 300px; height: 150px;" /></p>
844844
<p>Suppose we have <span class="math notranslate nohighlight">\(f(x): \{0,1\} \longrightarrow \{0,1\}\)</span>. We can compute this function on a quantum computer using oracles which we treat as black box functions that yield the output with an appropriate sequence of logical gates.</p>
845845
<p>Above you see an oracle represented as <span class="math notranslate nohighlight">\(U_f\)</span> which allows us to transform the state <span class="math notranslate nohighlight">\(\ket{x}\ket{y}\)</span> into:</p>
846846
<div class="math notranslate nohighlight">
@@ -888,7 +888,7 @@ <h2>Quantum parallelism<a class="headerlink" href="#Quantum-parallelism" title="
888888
<h2>Deutsch’s Algorithm:<a class="headerlink" href="#Deutsch's-Algorithm:" title="Permalink to this heading"></a></h2>
889889
<p>Our aim is to find out if <span class="math notranslate nohighlight">\(f: \{0,1\} \longrightarrow \{0,1\}\)</span> is a constant or a balanced function? If constant, <span class="math notranslate nohighlight">\(f(0) = f(1)\)</span>, and if balanced, <span class="math notranslate nohighlight">\(f(0) \neq f(1)\)</span>.</p>
890890
<p>We step through the circuit diagram below and follow the math after the application of each gate.</p>
891-
<p><img alt="35281ac32ad84616a5eaf09e7466bc67" class="no-scaled-link" src="../../_images/deutsch.png" style="width: 500px; height: 210px;" /></p>
891+
<p><img alt="1f5362b863664bc284d8007f42a2504d" class="no-scaled-link" src="../../_images/deutsch.png" style="width: 500px; height: 210px;" /></p>
892892
<div class="math notranslate nohighlight">
893893
\[\ket{\psi_0} = \ket{01}
894894
\tag{1}\]</div>

pr-2691/applications/python/quantum_transformer.html

+5-5
Large diffs are not rendered by default.

pr-2691/examples/python/performance_optimizations.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -768,9 +768,9 @@ <h1>Optimizing Performance<a class="headerlink" href="#Optimizing-Performance" t
768768
<section id="Gate-Fusion">
769769
<h2>Gate Fusion<a class="headerlink" href="#Gate-Fusion" title="Permalink to this heading"></a></h2>
770770
<p>Gate fusion is an optimization technique where consecutive gates are combined into a single gate operation to improve the efficiency of the simulation (See figure below). By targeting the <code class="docutils literal notranslate"><span class="pre">nvidia-mgpu</span></code> backend and setting the <code class="docutils literal notranslate"><span class="pre">CUDAQ_MGPU_FUSE</span></code> environment variable, you can select the degree of fusion that takes place. A full command line example would look like <code class="docutils literal notranslate"><span class="pre">CUDAQ_MGPU_FUSE=4</span> <span class="pre">python</span> <span class="pre">c2h2VQE.py</span> <span class="pre">--target</span> <span class="pre">nvidia</span> <span class="pre">--target-option</span> <span class="pre">fp64,mgpu</span></code></p>
771-
<p><img alt="6b6099816c1142f2a7b938ba56812e2c" src="../../_images/gate-fuse.png" /></p>
771+
<p><img alt="83deec047f434431852b55ff79b8738b" src="../../_images/gate-fuse.png" /></p>
772772
<p>The importance of gate fusion is system dependent, but can have a large influence on the performance of the simulation. See the example below for a 24 qubit VQE experiment where changing the fusion level resulted in significant performance boosts.</p>
773-
<p><img alt="3815aae6a1c341be8ea978bfdba1161d" src="../../_images/gatefusion.png" /></p>
773+
<p><img alt="fc6b27fe9bdd4001b73760a6a1699be7" src="../../_images/gatefusion.png" /></p>
774774
</section>
775775
</section>
776776

pr-2691/notebook_validation.py

+20-14
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
# the terms of the Apache License 2.0 which accompanies this distribution. #
77
# ============================================================================ #
88

9+
import time
910
import os
1011
import re
1112
import sys
@@ -42,11 +43,14 @@ def execute(notebook_filename):
4243
notebook_filename_out = notebook_filename.replace('.ipynb',
4344
'.nbconvert.ipynb')
4445
try:
46+
start_time = time.perf_counter()
4547
subprocess.run([
4648
"jupyter", "nbconvert", "--to", "notebook", "--execute",
4749
notebook_filename
4850
],
4951
check=True)
52+
elapsed = time.perf_counter() - start_time
53+
print(f"Time taken for nbconvert: {elapsed:.2f} seconds")
5054
os.remove(notebook_filename_out)
5155
return True
5256
except subprocess.CalledProcessError:
@@ -98,21 +102,23 @@ def print_results(success, failed, skipped=[]):
98102

99103
notebooks_success, notebooks_skipped, notebooks_failed = (
100104
[] for i in range(3))
105+
106+
## `afqmc`:
107+
## See: https://github.com/NVIDIA/cuda-quantum/issues/2577
108+
## `quantum_transformer`:
109+
## See: https://github.com/NVIDIA/cuda-quantum/issues/2689
110+
notebooks_skipped = ['afqmc.ipynb', 'quantum_transformer.ipynb']
111+
101112
for notebook_filename in notebook_filenames:
102-
## See: https://github.com/NVIDIA/cuda-quantum/issues/2577
103-
if os.path.basename(notebook_filename) in ["afqmc.ipynb"]:
104-
notebooks_skipped.append(notebook_filename)
105-
## See: https://github.com/NVIDIA/cuda-quantum/issues/2689
106-
if os.path.basename(notebook_filename) in [
107-
"quantum_transformer.ipynb"
108-
]:
109-
notebooks_skipped.append(notebook_filename)
110-
elif (validate(notebook_filename, available_backends)):
111-
if (execute(notebook_filename)):
112-
notebooks_success.append(notebook_filename)
113-
else:
114-
notebooks_failed.append(notebook_filename)
113+
base_name = os.path.basename(notebook_filename)
114+
if base_name in notebooks_skipped:
115+
continue # Already skipped, no need to re-check
116+
if not validate(notebook_filename, available_backends):
117+
notebooks_skipped.append(base_name)
118+
continue
119+
if execute(notebook_filename):
120+
notebooks_success.append(notebook_filename)
115121
else:
116-
notebooks_skipped.append(notebook_filename)
122+
notebooks_failed.append(notebook_filename)
117123

118124
print_results(notebooks_success, notebooks_failed, notebooks_skipped)

pr-2691/searchindex.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2022 - 2025 NVIDIA Corporation & Affiliates. *
3+
* All rights reserved. *
4+
* *
5+
* This source code and the accompanying materials are made available under *
6+
* the terms of the Apache License 2.0 which accompanies this distribution. *
7+
******************************************************************************/
8+
9+
// Compile and run with:
10+
// ```
11+
// nvq++ --target dynamics cavity_qed.cpp -o a.out && ./a.out
12+
// ```
13+
14+
#include "cudaq/algorithms/evolve.h"
15+
#include "cudaq/dynamics_integrators.h"
16+
#include "cudaq/operators.h"
17+
#include "export_csv_helper.h"
18+
#include <cudaq.h>
19+
20+
int main() {
21+
22+
// Dimension of our composite quantum system:
23+
// subsystem 0 (atom) has 2 levels (ground and excited states).
24+
// subsystem 1 (cavity) has 10 levels (Fock states, representing photon number
25+
// states).
26+
cudaq::dimension_map dimensions{{0, 2}, {1, 10}};
27+
28+
// For the cavity subsystem 1
29+
// We create the annihilation (a) and creation (a+) operators.
30+
// These operators lower and raise the photon number, respectively.
31+
auto a = cudaq::boson_operator::annihilate(1);
32+
auto a_dag = cudaq::boson_operator::create(1);
33+
34+
// For the atom subsystem 0
35+
// We create the annihilation (`sm`) and creation (`sm_dag`) operators.
36+
// These operators lower and raise the excitation number, respectively.
37+
auto sm = cudaq::boson_operator::annihilate(0);
38+
auto sm_dag = cudaq::boson_operator::create(0);
39+
40+
// Number operators
41+
// These operators count the number of excitations.
42+
// For the atom (`subsytem` 0) and the cavity (`subsystem` 1) they give the
43+
// population in each subsystem.
44+
auto atom_occ_op = cudaq::matrix_operator::number(0);
45+
auto cavity_occ_op = cudaq::matrix_operator::number(1);
46+
47+
// Hamiltonian
48+
// The `hamiltonian` models the dynamics of the atom-cavity (cavity QED)
49+
// system It has 3 parts:
50+
// 1. Cavity energy: 2 * pi * photon_number_operator -> energy proportional to
51+
// the number of photons.
52+
// 2. Atomic energy: 2 * pi * atom_number_operator -> energy proportional to
53+
// the atomic excitation.
54+
// 3. Atomic-cavity interaction: 2 * pi * 0.25 * (`sm` * a_dag + `sm_dag` * a)
55+
// -> represents the exchange of energy between the atom and the cavity. It is
56+
// analogous to the Jaynes-Cummings model in cavity QED.
57+
auto hamiltonian = (2 * M_PI * cavity_occ_op) + (2 * M_PI * atom_occ_op) +
58+
(2 * M_PI * 0.25 * (sm * a_dag + sm_dag * a));
59+
60+
// Build the initial state
61+
// Atom (sub-system 0) in ground state.
62+
// Cavity (sub-system 1) has 5 photons (Fock space).
63+
// The overall Hilbert space is 2 * 10 = 20.
64+
const int num_photons = 5;
65+
std::vector<std::complex<double>> initial_state_vec(20, 0.0);
66+
// The index is chosen such that the atom is in the ground state while the
67+
// cavity is in the Fock state with 5 photons.
68+
initial_state_vec[dimensions[0] * num_photons] = 1;
69+
70+
// Define a time evolution schedule
71+
// We define a time grid from 0 to 10 (in arbitrary time units) with 201 time
72+
// steps. This schedule is used by the integrator to simulate the dynamics.
73+
const int num_steps = 201;
74+
std::vector<double> steps = cudaq::linspace(0.0, 10.0, num_steps);
75+
cudaq::schedule schedule(steps);
76+
77+
// Create a CUDA quantum state
78+
// The initial state is converted into a quantum state object for evolution.
79+
auto rho0 = cudaq::state::from_data(initial_state_vec);
80+
81+
// Numerical integrator
82+
// Here we choose a Runge-`Kutta` method for time evolution.
83+
// `dt` defines the time step for the numerical integration, and order 4
84+
// indicates a 4`th` order method.
85+
cudaq::integrators::runge_kutta integrator(4, 0.01);
86+
87+
// Evolve without collapse operators
88+
// This evolution is ideal (closed system) dynamics governed solely by the
89+
// Hamiltonian. The expectation values of the observables (cavity photon
90+
// number and atom excitation probability) are recorded.
91+
cudaq::evolve_result evolve_result =
92+
cudaq::evolve(hamiltonian, dimensions, schedule, rho0, integrator, {},
93+
{cavity_occ_op, atom_occ_op}, true);
94+
95+
// Adding dissipation
96+
// To simulate a realistic scenario, we introduce decay (dissipation).
97+
// Here, the collapse operator represents photon loss from the cavity.
98+
constexpr double decay_rate = 0.1;
99+
auto collapse_operator = std::sqrt(decay_rate) * a;
100+
// Evolve with the collapse operator to incorporate the effect of decay.
101+
cudaq::evolve_result evolve_result_decay =
102+
cudaq::evolve(hamiltonian, dimensions, schedule, rho0, integrator,
103+
{collapse_operator}, {cavity_occ_op, atom_occ_op}, true);
104+
105+
// Lambda to extract expectation values for a given observable index
106+
// Here, index 0 corresponds to the cavity photon number and index 1
107+
// corresponds to the atom excitation probability.
108+
auto get_expectation = [](int idx, auto &result) -> std::vector<double> {
109+
std::vector<double> expectations;
110+
111+
auto all_exps = result.get_expectation_values().value();
112+
for (auto exp_vals : all_exps) {
113+
expectations.push_back((double)exp_vals[idx]);
114+
}
115+
return expectations;
116+
};
117+
118+
// Retrieve expectation values from both the ideal and decaying `evolutions`.
119+
auto ideal_result0 = get_expectation(0, evolve_result);
120+
auto ideal_result1 = get_expectation(1, evolve_result);
121+
auto decay_result0 = get_expectation(0, evolve_result_decay);
122+
auto decay_result1 = get_expectation(1, evolve_result_decay);
123+
124+
// Export the results to `CSV` files
125+
// "cavity_`qed`_ideal_result.`csv`" contains the ideal evolution results.
126+
// "cavity_`qed`_decay_result.`csv`" contains the evolution results with
127+
// cavity decay.
128+
export_csv("cavity_qed_ideal_result.csv", "time", steps,
129+
"cavity_photon_number", ideal_result0,
130+
"atom_excitation_probability", ideal_result1);
131+
export_csv("cavity_qed_decay_result.csv", "time", steps,
132+
"cavity_photon_number", decay_result0,
133+
"atom_excitation_probability", decay_result1);
134+
135+
std::cout << "Simulation complete. The results are saved in "
136+
"cavity_qed_ideal_result.csv "
137+
"and cavity_qed_decay_result.csv files."
138+
<< std::endl;
139+
return 0;
140+
}

0 commit comments

Comments
 (0)