Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs reviews #43

Merged
merged 47 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
c6419b8
Docs suggestions.
RolandMacDoland Oct 4, 2023
eb1911e
Fix typo.
RolandMacDoland Oct 4, 2023
c07aaad
Latest changes.
RolandMacDoland Oct 4, 2023
beb4aeb
Latest changes.
RolandMacDoland Oct 4, 2023
3483dab
Trigger docs tests on CI.
RolandMacDoland Oct 4, 2023
0816260
More files to docs.
RolandMacDoland Oct 4, 2023
58e0f08
fix circuit drawings
jpmoutinho Oct 4, 2023
9731a21
quadance to qadance
jpmoutinho Oct 4, 2023
0ddbd1d
More docs improvements.
RolandMacDoland Oct 4, 2023
e62772c
Merge branch 'main' into rg/docs-reviews
jpmoutinho Oct 5, 2023
7fe38a7
fix docs build
jpmoutinho Oct 5, 2023
536732b
More suggestions and run test-docs again.
RolandMacDoland Oct 5, 2023
fc1f3ec
update pulser examples
vytautas-a Oct 5, 2023
5b3a936
remove mkdocs-jupyter
jpmoutinho Oct 5, 2023
02e9deb
Merge branch 'rg/docs-reviews' of github.com:pasqal-io/qadence into r…
jpmoutinho Oct 5, 2023
eaa094d
update pulser example
vytautas-a Oct 5, 2023
3d17963
More improvements.
RolandMacDoland Oct 5, 2023
c410499
Fix lint.
RolandMacDoland Oct 5, 2023
b8340df
More docs suggestions.
RolandMacDoland Oct 6, 2023
00840ed
More and more suggestions.
RolandMacDoland Oct 6, 2023
9512b78
Merge branch 'main' into rg/docs-reviews
RolandMacDoland Oct 6, 2023
c01a96b
More suggestions.
RolandMacDoland Oct 6, 2023
03d57b9
More suggestions.
RolandMacDoland Oct 8, 2023
052ad4d
Concatenate two doc files.
RolandMacDoland Oct 8, 2023
2e4a1df
Move to qml_tools.md
RolandMacDoland Oct 8, 2023
a58d5ae
More suggestions.
RolandMacDoland Oct 8, 2023
b898e28
update entanglement tests
vytautas-a Oct 9, 2023
f1ab971
few fixes
jpmoutinho Oct 9, 2023
743a1a7
pulser-basic tutorial broken
jpmoutinho Oct 9, 2023
160464c
few fixes
jpmoutinho Oct 9, 2023
ff011bf
few fixes
jpmoutinho Oct 9, 2023
14d6de6
more fixes
jpmoutinho Oct 9, 2023
044004c
remove total_magnetization from docs
jpmoutinho Oct 9, 2023
7cdda44
remove emuc
jpmoutinho Oct 9, 2023
cd96880
fix entanglement test
vytautas-a Oct 9, 2023
69d779a
fix entanglement test
vytautas-a Oct 9, 2023
60e0f12
Update docs/advanced_tutorials/custom-models.md
RolandMacDoland Oct 9, 2023
5f4b2c7
Update docs/advanced_tutorials/differentiability.md
RolandMacDoland Oct 9, 2023
1fc6729
Update docs/digital_analog_qc/pulser-basic.md
RolandMacDoland Oct 9, 2023
cb28fe1
Update docs/tutorials/ml_tools.md
RolandMacDoland Oct 9, 2023
8fd59e5
Update docs/tutorials/qml_tools.md
RolandMacDoland Oct 9, 2023
7779ca0
Update docs/tutorials/ml_tools.md
RolandMacDoland Oct 9, 2023
d03d9df
Update docs/tutorials/qml_tools.md
RolandMacDoland Oct 9, 2023
e80fd71
Update docs/tutorials/serializ_and_prep.md
RolandMacDoland Oct 9, 2023
f5b48f7
More suggestions.
RolandMacDoland Oct 9, 2023
359ad97
Merge branch 'main' into rg/docs-reviews
RolandMacDoland Oct 9, 2023
4aa4c3c
Fix conflicts.
RolandMacDoland Oct 9, 2023
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
4 changes: 2 additions & 2 deletions docs/advanced_tutorials/custom-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class CustomQuantumModel(QuantumModel):
The custom model can be used like any other `QuantumModel`:
```python exec="on" source="material-block" result="json" session="custom-model"
from qadence import Parameter, RX, CNOT, QuantumCircuit
from qadence import chain, kron, total_magnetization
from qadence import chain, kron, hamiltonian_factory, Z
from sympy import acos

def quantum_circuit(n_qubits):
Expand All @@ -64,7 +64,7 @@ def quantum_circuit(n_qubits):
n_qubits = 4
batch_size = 10
circuit = quantum_circuit(n_qubits)
observable = total_magnetization(n_qubits)
observable = hamiltonian_factory(n_qubits, detuning = Z) # Total magnetization
RolandMacDoland marked this conversation as resolved.
Show resolved Hide resolved

model = CustomQuantumModel(circuit, observable, backend="pyqtorch")

Expand Down
4 changes: 2 additions & 2 deletions docs/advanced_tutorials/differentiability.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ In Qadence, the GPSR differentiation engine can be selected by passing `diff_mod

```python exec="on" source="material-block" session="differentiability"
from qadence import (FeatureParameter, HamEvo, X, I, Z,
total_magnetization, QuantumCircuit,
hamiltonian_factory, QuantumCircuit,
QuantumModel, BackendName, DiffMode)
import torch

Expand All @@ -83,7 +83,7 @@ block = HamEvo(generator, x)
circuit = QuantumCircuit(n_qubits, block)

# create total magnetization cost operator
obs = total_magnetization(n_qubits)
obs = hamiltonian_factory(n_qubits, detuning = Z)
RolandMacDoland marked this conversation as resolved.
Show resolved Hide resolved

# create models with AD and GPSR differentiation engines
model_ad = QuantumModel(circuit, obs,
Expand Down
189 changes: 100 additions & 89 deletions docs/digital_analog_qc/pulser-basic.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
!!! warning
This tutorial needs to be fixed.


Qadence offers a direct interface with Pulser[^1], an open-source pulse-level interface written in Python and specifically designed for programming neutral atom quantum computers.

Using directly Pulser requires deep knowledge on pulse-level programming and on how neutral atom devices work. Qadence abstracts out this complexity by using the familiar block-based interface for building pulse sequences in Pulser while leaving the possibility
Expand Down Expand Up @@ -54,7 +58,7 @@ bell_state = chain(
To convert the chain block into a pulse sequence, we define a `Register` with two qubits and combine it to create a circuit as usual. Then we construct a `QuantumModel` with a Pulser backend to convert it into a proper parametrized pulse sequence. Supplying the
parameter values allows to sample from the pulse sequence result.

```python exec="on" source="material-block" session="pulser-basic"
```python exec="on" source="material-block" "html=1" session="pulser-basic"
import torch
import matplotlib.pyplot as plt
from qadence import Register, QuantumCircuit, QuantumModel
Expand Down Expand Up @@ -96,7 +100,10 @@ At variance with other backends, the Pulser one provides the concept of `Device`

A `Device` instance encapsulate all the properties defining a real neutral atoms processor, including but not limited to the maximum laser amplitude for the pulses, the maximum distance between two qubits and the maximum duration of the pulse.

`qadence` offers a simplified interface with only two devices which can be found [here][qadence.backends.pulser.devices]
!!! warning
Fix link below.

`qadence` offers a simplified interface with only two devices which can be found [here](/backends.pulser.devices)
RolandMacDoland marked this conversation as resolved.
Show resolved Hide resolved

* `IDEALIZED` (default): ideal device which should be used only for testing purposes. It does not have any limitation in what can be run with it.
* `REALISTIC`: device specification very similar to a real neutral atom quantum processor.
Expand All @@ -121,16 +128,17 @@ model = QuantumModel(
configuration={"device_type": Device.REALISTIC}
)

# alternatively directly one of the devices available in Pulser
# can also be supplied in the same way
from pulser.devices import AnalogDevice

model = QuantumModel(
circuit,
backend="pulser",
diff_mode="gpsr",
configuration={"device_type": AnalogDevice}
)
# FIXME: Specified device is not supported.
# # alternatively directly one of the devices available in Pulser
# # can also be supplied in the same way
# from pulser.devices import AnalogDevice

# model = QuantumModel(
# circuit,
# backend="pulser",
# diff_mode="gpsr",
# configuration={"device_type": AnalogDevice}
# )
```

## Create your own gate
Expand All @@ -156,32 +164,33 @@ obs = [zz, xy + yx]

Now we define the `QuantumModel` and pass the observable list to it together with the constructed circuit.

```python exec="on" source="material-block" result="json" session="pulser-basic"
from qadence import RX, AnalogRot
```python exec="on" source="material-block" html="1" session="pulser-basic"
# FIXME: protocol not defined
# from qadence import RX, AnalogRot

register = Register(2)
circuit = QuantumCircuit(register, protocol)
model = QuantumModel(circuit, backend="pulser", diff_mode='gpsr')
# register = Register(2)
# circuit = QuantumCircuit(register, protocol)
# model = QuantumModel(circuit, backend="pulser", diff_mode='gpsr')

params = {
"t": torch.tensor([383]), # ns
"y": torch.tensor([torch.pi / 2]),
}
# params = {
# "t": torch.tensor([383]), # ns
# "y": torch.tensor([torch.pi / 2]),
# }

sample = model.sample(params, n_shots=50)[0]
# sample = model.sample(params, n_shots=50)[0]

fig, ax = plt.subplots()
plt.bar(sample.keys(), sample.values())
from docs import docsutils # markdown-exec: hide
print(docsutils.fig_to_html(fig)) # markdown-exec: hide
# fig, ax = plt.subplots()
# plt.bar(sample.keys(), sample.values())
# from docs import docsutils # markdown-exec: hide
# print(docsutils.fig_to_html(fig)) # markdown-exec: hide
```

One can also easily access and manipulate the underlying pulse sequence.

```python exec="on" source="material-block" html="1" session="pulser-basic"
model.assign_parameters(params).draw(draw_phase_area=True, show=False)
from docs import docsutils # markdown-exec: hide
print(docsutils.fig_to_html(plt.gcf())) # markdown-exec: hide
# model.assign_parameters(params).draw(draw_phase_area=True, show=False)
# from docs import docsutils # markdown-exec: hide
# print(docsutils.fig_to_html(plt.gcf())) # markdown-exec: hide
```

## Large qubits registers
Expand All @@ -191,48 +200,50 @@ with two or three qubits. But for the blocks we have so far, large registers
work better with a square loop layout like the following.

```python exec="on" source="material-block" html="1" session="pulser-basic"
register = Register.square(qubits_side=4)
register.draw(show=False)
from docs import docsutils # markdown-exec: hide
print(docsutils.fig_to_html(plt.gcf())) # markdown-exec: hide
# register = Register.square(qubits_side=4)
# register.draw(show=False)
# from docs import docsutils # markdown-exec: hide
# print(docsutils.fig_to_html(plt.gcf())) # markdown-exec: hide
```

In those cases, global pulses are preferred to generate entanglement to avoid
changing the addressing pattern on the fly.

```python exec="on" source="material-block" html="1" session="pulser-basic"
protocol = chain(
entangle("t"),
AnalogRY(torch.pi / 2),
)
# from qadence import AnalogRY

register = Register.square(qubits_side=2)
circuit = QuantumCircuit(register, protocol)
model = QuantumModel(circuit, backend="pulser", diff_mode="gpsr")
# protocol = chain(
# entangle("t"),
# AnalogRY(torch.pi / 2),
# )

# add modulation to the pulse sequence by modifying the
# backend configuration
model.backend.backend.config.with_modulation = True
# register = Register.square(qubits_side=2)
# circuit = QuantumCircuit(register, protocol)
# model = QuantumModel(circuit, backend="pulser", diff_mode="gpsr")

params = {
"x": torch.tensor([3*torch.pi/2]), # ns
}
# # add modulation to the pulse sequence by modifying the
# # backend configuration
# model.backend.backend.config.with_modulation = True

sample = model.sample(params, n_shots=500)[0]
# params = {
# "x": torch.tensor([3*torch.pi/2]), # ns
# }

fig, ax = plt.subplots()
ax.bar(sample.keys(), sample.values())
plt.xticks(rotation='vertical')
from docs import docsutils # markdown-exec: hide
print(docsutils.fig_to_html(fig)) # markdown-exec: hide
# sample = model.sample(params, n_shots=500)[0]

# fig, ax = plt.subplots()
# ax.bar(sample.keys(), sample.values())
# plt.xticks(rotation='vertical')
# from docs import docsutils # markdown-exec: hide
# print(docsutils.fig_to_html(fig)) # markdown-exec: hide
```

Again, let's plot the corresponding pulse sequence.

```python exec="on" source="material-block" html="1" session="pulser-basic"
model.assign_parameters(params).draw(draw_phase_area=True, show=False)
from docs import docsutils # markdown-exec: hide
print(docsutils.fig_to_html(plt.gcf())) # markdown-exec: hide
# model.assign_parameters(params).draw(draw_phase_area=True, show=False)
# from docs import docsutils # markdown-exec: hide
# print(docsutils.fig_to_html(plt.gcf())) # markdown-exec: hide
```

!!! note
Expand All @@ -247,40 +258,40 @@ version of a quantum neural network circuit with feature map and variational
ansatz.

```python exec="on" source="material-block" html="1" session="pulser-basic"
from qadence import kron, fourier_feature_map
from qadence.operations import RX, RY, AnalogRX

hea_one_layer = chain(
kron(RY(0, "th00"), RY(1, "th01")),
kron(RX(0, "th10"), RX(1, "th11")),
kron(RY(0, "th20"), RY(1, "th21")),
entangle("t", qubit_support=(0,1)),
)

protocol = chain(
fourier_feature_map(1, param="x"),
hea_one_layer,
AnalogRX(torch.pi/4)
)

register = Register(2)
circuit = QuantumCircuit(register, protocol)
model = QuantumModel(circuit, backend="pulser", diff_mode="gpsr")

params = {
"x": torch.tensor([0.8]), # rad
"t": torch.tensor([900]), # ns
"th00": torch.rand(1), # rad
"th01": torch.rand(1), # rad
"th10": torch.rand(1), # rad
"th11": torch.rand(1), # rad
"th20": torch.rand(1), # rad
"th21": torch.rand(1), # rad
}

model.assign_parameters(params).draw(draw_phase_area=True, show=True)
from docs import docsutils # markdown-exec: hide
print(docsutils.fig_to_html(plt.gcf())) # markdown-exec: hide
# from qadence import kron, fourier_feature_map
# from qadence.operations import RX, RY, AnalogRX

# hea_one_layer = chain(
# kron(RY(0, "th00"), RY(1, "th01")),
# kron(RX(0, "th10"), RX(1, "th11")),
# kron(RY(0, "th20"), RY(1, "th21")),
# entangle("t", qubit_support=(0,1)),
# )

# protocol = chain(
# fourier_feature_map(1, param="x"),
# hea_one_layer,
# AnalogRX(torch.pi/4)
# )

# register = Register(2)
# circuit = QuantumCircuit(register, protocol)
# model = QuantumModel(circuit, backend="pulser", diff_mode="gpsr")

# params = {
# "x": torch.tensor([0.8]), # rad
# "t": torch.tensor([900]), # ns
# "th00": torch.rand(1), # rad
# "th01": torch.rand(1), # rad
# "th10": torch.rand(1), # rad
# "th11": torch.rand(1), # rad
# "th20": torch.rand(1), # rad
# "th21": torch.rand(1), # rad
# }

# model.assign_parameters(params).draw(draw_phase_area=True, show=True)
# from docs import docsutils # markdown-exec: hide
# print(docsutils.fig_to_html(plt.gcf())) # markdown-exec: hide
```

## References
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ For a more comprehensive introduction and advanced topics, please have a look at
* [Basic tutorials](tutorials/getting_started.md) for first hands-on.
* [Digital-analog basics](digital_analog_qc/analog-basics.md) to build quantum programs in the digital-analog paradigm.
* [Parametric quantum circuits](tutorials/parameters.md) for the generation and manipulation of parametric programs.
* [Advanced features](advanced_tutorials) about low-level backend interface and differentiablity.
* [Advanced features](advanced_tutorials/differentiability.md) about low-level backend interface and differentiablity.
* [`QuantumModel`](advanced_tutorials/custom-models.md) for defining custom models.

## Installation guide
Expand Down
2 changes: 1 addition & 1 deletion docs/qml/qcl.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ ansatz = qd.hea(n_qubits, depth=n_qubits, strategy=qd.Strategy.SDAQC)
ansatz = qd.tag(ansatz, "ansatz")

# total magnetization observable
observable = qd.total_magnetization(n_qubits)
observable = qd.hamiltonian_factory(n_qubits, detuning = qd.Z)
RolandMacDoland marked this conversation as resolved.
Show resolved Hide resolved

circuit = qd.QuantumCircuit(n_qubits, feature_map, ansatz)
model = qd.QNN(circuit, [observable])
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ which follow a more object-oriented way to construct circuits and express progra

```python exec="on" source="material-block" html="1"
from qadence import X, Y, kron
from visualization import display
from qadence.draw import display

kron_block = kron(X(0), Y(1))
display(kron_block)
Expand Down
12 changes: 6 additions & 6 deletions docs/tutorials/ml_tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,16 @@ Let's look at a complete example of how to use `train_with_grad` now.
from pathlib import Path
import torch
from itertools import count
from qadence.constructors import total_magnetization, hea, feature_map
from qadence import chain, Parameter, QuantumCircuit
from qadence.constructors import hamiltonian_factory, hea, feature_map
from qadence import chain, Parameter, QuantumCircuit, Z
from qadence.models import QNN
from qadence.ml_tools import train_with_grad, TrainConfig
import matplotlib.pyplot as plt

n_qubits = 2
fm = feature_map(n_qubits)
ansatz = hea(n_qubits=n_qubits, depth=3)
observable = total_magnetization(n_qubits)
observable = hamiltonian_factory(n_qubits, detuning = Z)
RolandMacDoland marked this conversation as resolved.
Show resolved Hide resolved
circuit = QuantumCircuit(n_qubits, fm, ansatz)

model = QNN(circuit, observable, backend="pyqtorch", diff_mode="ad")
Expand Down Expand Up @@ -111,15 +111,15 @@ written without `train_with_grad`.
from pathlib import Path
import torch
from itertools import count
from qadence.constructors import total_magnetization, hea, feature_map
from qadence import chain, Parameter, QuantumCircuit
from qadence.constructors import hamiltonian_factory, hea, feature_map
from qadence import chain, Parameter, QuantumCircuit, Z
from qadence.models import QNN
from qadence.ml_tools import train_with_grad, TrainConfig

n_qubits = 2
fm = feature_map(n_qubits)
ansatz = hea(n_qubits=n_qubits, depth=3)
observable = total_magnetization(n_qubits)
observable = hamiltonian_factory(n_qubits, detuning = Z)
RolandMacDoland marked this conversation as resolved.
Show resolved Hide resolved
circuit = QuantumCircuit(n_qubits, fm, ansatz)

model = QNN(circuit, observable, backend="pyqtorch", diff_mode="ad")
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ print(html_string(circuit)) # markdown-exec: hide
print(html_string(circuit)) # markdown-exec: hide
```

The `hea` function will be further explored in the [QML Constructors tutorial](qml_constructors.md).
The `hea` function will be further explored in the [QML Constructors tutorial](qml_tools.md).

## Parametric observables

Expand Down
Loading
Loading