Skip to content

Commit 7903c8b

Browse files
Improve photonics documentation (#2502)
* photonics simulator Signed-off-by: Omar Bacarreza <[email protected]> * photonics operators Signed-off-by: Omar Bacarreza <[email protected]> * executing photonic kernels Signed-off-by: Omar Bacarreza <[email protected]> * formatting and spelling Signed-off-by: Omar Bacarreza <[email protected]> * Update annihilate_photonic_gate.py Signed-off-by: Omar Bacarreza <[email protected]> * Add header to beam_splitter_photonic_gate.py Signed-off-by: Omar Bacarreza <[email protected]> * patch photonics_tbi*.cpp Signed-off-by: Omar Bacarreza <[email protected]> * Library mode required Signed-off-by: Pradnya Khalate <[email protected]> * Update annihilate_photonic_gate.py Co-authored-by: Pradnya Khalate <[email protected]> Signed-off-by: Omar Bacarreza <[email protected]> --------- Signed-off-by: Omar Bacarreza <[email protected]> Signed-off-by: Pradnya Khalate <[email protected]> Signed-off-by: Omar Bacarreza <[email protected]> Co-authored-by: Pradnya Khalate <[email protected]>
1 parent c890e46 commit 7903c8b

11 files changed

+487
-4
lines changed

.github/workflows/config/spelling_allowlist.txt

+6
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ MPI
6363
MPICH
6464
MPS
6565
MSB
66+
Mandel
6667
Max-Cut
6768
MyST
6869
NGC
@@ -78,10 +79,12 @@ OpenMPI
7879
OpenQASM
7980
OpenSSL
8081
OpenSUSE
82+
Ou
8183
POSIX
8284
PSIRT
8385
Pauli
8486
Paulis
87+
Photonics
8588
PyPI
8689
Pygments
8790
QAOA
@@ -136,6 +139,7 @@ backends
136139
bitcode
137140
bitstring
138141
bitstrings
142+
bmatrix
139143
bool
140144
boolean
141145
boson
@@ -168,6 +172,7 @@ cuQuantum
168172
cuTensor
169173
cudaq
170174
dataflow
175+
ddots
171176
deallocate
172177
deallocated
173178
deallocates
@@ -322,6 +327,7 @@ unoptimized
322327
upvote
323328
variadic
324329
variational
330+
vdots
325331
verifier
326332
vertices
327333
waveforms

docs/sphinx/api/default_ops.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,7 @@ defined by the qudit level that represents the qumode. If it is applied to a qum
650650
where the number of photons is already at the maximum value, the operation has no
651651
effect.
652652

653-
:math:`U|0\rangle → |1\rangle, U|1\rangle → |2\rangle, U|2\rangle → |3\rangle, \cdots, U|d\rangle → |d\rangle`
653+
:math:`C|0\rangle → |1\rangle, C|1\rangle → |2\rangle, C|2\rangle → |3\rangle, \cdots, C|d\rangle → |d\rangle`
654654
where :math:`d` is the qudit level.
655655

656656
.. tab:: Python
@@ -674,7 +674,7 @@ This operation reduces the number of photons in a qumode up to a minimum value o
674674
0 representing the vacuum state. If it is applied to a qumode where the number of
675675
photons is already at the minimum value 0, the operation has no effect.
676676

677-
:math:`U|0\rangle → |0\rangle, U|1\rangle → |0\rangle, U|2\rangle → |1\rangle, \cdots, U|d\rangle → |d-1\rangle`
677+
:math:`A|0\rangle → |0\rangle, A|1\rangle → |0\rangle, A|2\rangle → |1\rangle, \cdots, A|d\rangle → |d-1\rangle`
678678
where :math:`d` is the qudit level.
679679

680680
.. tab:: Python
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
{
2+
"cells": [
3+
{
4+
"attachments": {},
5+
"cell_type": "markdown",
6+
"metadata": {},
7+
"source": [
8+
"# Executing Quantum Photonic Circuits \n",
9+
"\n",
10+
"In CUDA-Q, there are 2 ways in which one can execute quantum photonic kernels: \n",
11+
"\n",
12+
"1. `sample`: yields measurement counts \n",
13+
"3. `get_state`: yields the quantum statevector of the computation \n",
14+
"\n",
15+
"## Sample\n",
16+
"\n",
17+
"Quantum states collapse upon measurement and hence need to be sampled many times to gather statistics. The CUDA-Q `sample` call enables this: \n",
18+
"\n"
19+
]
20+
},
21+
{
22+
"cell_type": "code",
23+
"execution_count": null,
24+
"metadata": {},
25+
"outputs": [],
26+
"source": [
27+
"import cudaq\n",
28+
"import numpy as np\n",
29+
"\n",
30+
"qumode_count = 2\n",
31+
"\n",
32+
"# Define the simulation target.\n",
33+
"cudaq.set_target(\"orca-photonics\")\n",
34+
"\n",
35+
"# Define a quantum kernel function.\n",
36+
"\n",
37+
"\n",
38+
"@cudaq.kernel\n",
39+
"def kernel(qumode_count: int):\n",
40+
" level = qumode_count + 1\n",
41+
" qumodes = [qudit(level) for _ in range(qumode_count)]\n",
42+
"\n",
43+
" # Apply the create gate to the qumodes.\n",
44+
" for i in range(qumode_count):\n",
45+
" create(qumodes[i]) # |00⟩ -> |11⟩\n",
46+
"\n",
47+
" # Apply the beam_splitter gate to the qumodes.\n",
48+
" beam_splitter(qumodes[0], qumodes[1], np.pi / 6)\n",
49+
"\n",
50+
" # measure all qumodes\n",
51+
" mz(qumodes)\n",
52+
"\n",
53+
"\n",
54+
"result = cudaq.sample(kernel, qumode_count, shots_count=1000)\n",
55+
"\n",
56+
"print(result)"
57+
]
58+
},
59+
{
60+
"cell_type": "markdown",
61+
"metadata": {},
62+
"source": [
63+
"\n",
64+
"## Get state\n",
65+
"\n",
66+
"The `get_state` function gives us access to the quantum statevector of the computation."
67+
]
68+
},
69+
{
70+
"cell_type": "code",
71+
"execution_count": null,
72+
"metadata": {},
73+
"outputs": [],
74+
"source": [
75+
"import cudaq\n",
76+
"import numpy as np\n",
77+
"\n",
78+
"qumode_count = 2\n",
79+
"\n",
80+
"# Define the simulation target.\n",
81+
"cudaq.set_target(\"orca-photonics\")\n",
82+
"\n",
83+
"# Define a quantum kernel function.\n",
84+
"\n",
85+
"\n",
86+
"@cudaq.kernel\n",
87+
"def kernel(qumode_count: int):\n",
88+
" level = qumode_count + 1\n",
89+
" qumodes = [qudit(level) for _ in range(qumode_count)]\n",
90+
"\n",
91+
" # Apply the create gate to the qumodes.\n",
92+
" for i in range(qumode_count):\n",
93+
" create(qumodes[i]) # |00⟩ -> |11⟩\n",
94+
"\n",
95+
" # Apply the beam_splitter gate to the qumodes.\n",
96+
" beam_splitter(qumodes[0], qumodes[1], np.pi / 6)\n",
97+
"\n",
98+
" # measure some of all qumodes if need to be measured\n",
99+
" # mz(qumodes)\n",
100+
"\n",
101+
"\n",
102+
"# Compute the statevector of the kernel\n",
103+
"result = cudaq.get_state(kernel, qumode_count)\n",
104+
"\n",
105+
"print(np.array(result))"
106+
]
107+
},
108+
{
109+
"cell_type": "markdown",
110+
"metadata": {},
111+
"source": [
112+
"The statevector generated by the `get_state` command follows little-endian convention for associating numbers with their digit string representations, which places the least significant digit on the right. That is, for the example of a 2-qumode system of level 3 (in which possible states are 0, 1, and 2), we have the following translation between integers and digit string:\n",
113+
"$$\\begin{matrix} \n",
114+
"\\text{Integer} & \\text{digit string representation}\\\\\n",
115+
"& \\text{least significant bit on right}\\\\\n",
116+
"0 = \\textcolor{blue}{0}*3^1 + \\textcolor{red}{0}*3^0 & \\textcolor{blue}{0}\\textcolor{red}{0} \\\\\n",
117+
"1 = \\textcolor{blue}{0}*3^1 + \\textcolor{red}{1}*3^0 & \\textcolor{blue}{0}\\textcolor{red}{1}\\\\\n",
118+
"2 = \\textcolor{blue}{0}*3^1 + \\textcolor{red}{2}*3^0 & \\textcolor{blue}{0}\\textcolor{red}{2}\\\\\n",
119+
"3 = \\textcolor{blue}{1}*3^1 + \\textcolor{red}{0}*3^0 & \\textcolor{blue}{1}\\textcolor{red}{0} \\\\\n",
120+
"4 = \\textcolor{blue}{1}*3^1 + \\textcolor{red}{1}*3^0 & \\textcolor{blue}{1}\\textcolor{red}{1} \\\\\n",
121+
"5 = \\textcolor{blue}{1}*3^1 + \\textcolor{red}{2}*3^0 & \\textcolor{blue}{1}\\textcolor{red}{2} \\\\\n",
122+
"6 = \\textcolor{blue}{2}*3^1 + \\textcolor{red}{0}*3^0 & \\textcolor{blue}{2}\\textcolor{red}{0} \\\\\n",
123+
"7 = \\textcolor{blue}{2}*3^1 + \\textcolor{red}{1}*3^0 & \\textcolor{blue}{2}\\textcolor{red}{1} \\\\\n",
124+
"8 = \\textcolor{blue}{2}*3^1 + \\textcolor{red}{2}*3^0 & \\textcolor{blue}{2}\\textcolor{red}{2} \n",
125+
"\\end{matrix}\n",
126+
"$$\n"
127+
]
128+
},
129+
{
130+
"attachments": {},
131+
"cell_type": "markdown",
132+
"metadata": {},
133+
"source": [
134+
"\n",
135+
"## Parallelization Techniques\n",
136+
"\n",
137+
"The most intensive task in the computation is the execution of the quantum photonic kernel hence each execution function: `sample`, and `get_state` can be parallelized given access to multiple quantum processing units (multi-QPU). We emulate each QPU with a CPU."
138+
]
139+
},
140+
{
141+
"cell_type": "code",
142+
"execution_count": null,
143+
"metadata": {},
144+
"outputs": [],
145+
"source": [
146+
"print(cudaq.__version__)"
147+
]
148+
}
149+
],
150+
"metadata": {
151+
"kernelspec": {
152+
"display_name": "Python 3",
153+
"language": "python",
154+
"name": "python3"
155+
},
156+
"language_info": {
157+
"codemirror_mode": {
158+
"name": "ipython",
159+
"version": 3
160+
},
161+
"file_extension": ".py",
162+
"mimetype": "text/x-python",
163+
"name": "python",
164+
"nbconvert_exporter": "python",
165+
"pygments_lexer": "ipython3",
166+
"version": "3.10.12"
167+
}
168+
},
169+
"nbformat": 4,
170+
"nbformat_minor": 4
171+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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+
#[Begin Docs]
10+
import cudaq
11+
12+
cudaq.set_target("orca-photonics")
13+
14+
15+
@cudaq.kernel
16+
def kernel():
17+
# A single qumode with 2 levels initialized to the ground / zero state.
18+
level = 2
19+
qumode = qudit(level)
20+
21+
# Apply the create gate to the qumode.
22+
create(qumode) # |0⟩ -> |1⟩
23+
24+
# Apply the annihilate gate to the qumode.
25+
annihilate(qumode) # |1⟩ -> |0⟩
26+
27+
# Measurement operator.
28+
mz(qumode)
29+
30+
31+
# Sample the qumode for 1000 shots to gather statistics.
32+
# In this case, the results are deterministic and all return state 0.
33+
result = cudaq.sample(kernel)
34+
print(result)
35+
#[End Docs]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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+
#[Begin Docs]
10+
import cudaq
11+
import math
12+
13+
cudaq.set_target("orca-photonics")
14+
15+
16+
@cudaq.kernel
17+
def kernel():
18+
n_modes = 2
19+
level = 3 # qudit level
20+
21+
# Two qumode with 3 levels initialized to the ground / zero state.
22+
qumodes = [qudit(level) for _ in range(n_modes)]
23+
24+
# Apply the create gate to the qumodes.
25+
for i in range(n_modes):
26+
create(qumodes[i]) # |00⟩ -> |11⟩
27+
28+
# Apply the beam_splitter gate to the qumodes.
29+
beam_splitter(qumodes[0], qumodes[1], math.pi / 4)
30+
31+
# Measurement operator.
32+
mz(qumodes)
33+
34+
35+
# Sample the qumode for 1000 shots to gather statistics.
36+
result = cudaq.sample(kernel)
37+
print(result)
38+
#[End Docs]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
#[Begin Docs]
10+
import cudaq
11+
12+
cudaq.set_target("orca-photonics")
13+
14+
15+
@cudaq.kernel
16+
def kernel():
17+
# A single qumode with 2 levels initialized to the ground / zero state.
18+
level = 2
19+
qumode = qudit(level)
20+
21+
# Apply the create gate to the qumode.
22+
create(qumode) # |0⟩ -> |1⟩
23+
24+
# Measurement operator.
25+
mz(qumode)
26+
27+
28+
# Sample the qumode for 1000 shots to gather statistics.
29+
# In this case, the results are deterministic and all return state 1.
30+
result = cudaq.sample(kernel)
31+
print(result)
32+
#[End Docs]

docs/sphinx/targets/cpp/photonics_tbi_get_state.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Compile and run with:
22
// ```
3-
// nvq++ --target orca-photonics photonics_tbi_get_state.cpp && ./a.out
3+
// nvq++ --library-mode --target orca-photonics photonics_tbi_get_state.cpp
4+
// ./a.out
45
// ```
56

67
#include <cudaq.h>

docs/sphinx/targets/cpp/photonics_tbi_sample.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Compile and run with:
22
// ```
3-
// nvq++ --target orca-photonics photonics_tbi_sample.cpp && ./a.out
3+
// nvq++ --library-mode --target orca-photonics photonics_tbi_sample.cpp
4+
// ./a.out
45
// ```
56

67
#include <cudaq.h>

0 commit comments

Comments
 (0)