Skip to content

Commit

Permalink
[Feature | Refac | Breaking] Rework QNN, Remove TransformedModule, Ad…
Browse files Browse the repository at this point in the history
…d Configs (#385)
  • Loading branch information
dominikandreasseitz authored Jun 21, 2024
1 parent d9a253f commit 6ad3ef5
Show file tree
Hide file tree
Showing 54 changed files with 1,996 additions and 1,044 deletions.
4 changes: 3 additions & 1 deletion docs/api/ml_tools.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## ML Tools

This module implements gradient-free and gradient-based training loops for torch Modules and QuantumModel.
This module implements gradient-free and gradient-based training loops for torch Modules and QuantumModel. It also implements the QNN class.

### ::: qadence.ml_tools.config

Expand All @@ -13,3 +13,5 @@ This module implements gradient-free and gradient-based training loops for torch
### ::: qadence.ml_tools.train_no_grad

### ::: qadence.ml_tools.data

### ::: qadence.ml_tools.models
4 changes: 2 additions & 2 deletions docs/api/models.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
::: qadence.models.quantum_model
::: qadence.model

::: qadence.models.qnn
::: qadence.ml_tools.models.QNN
4 changes: 2 additions & 2 deletions docs/content/quantummodels.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
A quantum program can be expressed and executed using the [`QuantumModel`][qadence.models.quantum_model.QuantumModel] type.
A quantum program can be expressed and executed using the [`QuantumModel`][qadence.model.QuantumModel] type.
It serves three primary purposes:

_**Parameter handling**_: by conveniently handling and embedding the two parameter types that Qadence supports:
Expand Down Expand Up @@ -122,7 +122,7 @@ model = QuantumModel(circuit, observable)
## Quantum Neural Network (QNN)

The `QNN` is a subclass of the `QuantumModel` geared towards quantum machine learning and parameter optimisation. See the
[quantum machine learning section](../tutorials/qml/index.md) section or the [`QNN` API reference][qadence.models.QNN] for more detailed
[quantum machine learning section](../tutorials/qml/index.md) section or the [`QNN` API reference][qadence.ml_tools.models.QNN] for more detailed
information. There are three main differences in interface when compared with the `QuantumModel`:

- It is initialized with a list of the input parameter names, and then supports direct `torch.Tensor` inputs instead of the values dictionary shown above. The ordering of the input values should respect the order given in the input names.
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/development/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ In Qadence there are 4 main objects spread across 3 different levels of abstract
* [`QuantumCircuit`][qadence.circuit.QuantumCircuit]: A class representing an abstract quantum
circuit not tight not any particular framework. Parameters are represented symbolically using
`sympy` expressions.
* [`QuantumModel`][qadence.models.QuantumModel]: The models are higher-level abstraction
* [`QuantumModel`][qadence.QuantumModel]: The models are higher-level abstraction
providing an interface for executing different kinds of common quantum computing models such
quantum neural networks (QNNs), quantum kernels etc.

Expand Down
105 changes: 105 additions & 0 deletions docs/tutorials/qml/config_qnn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
In `qadence`, the [`QNN`][qadence.ml_tools.models.QNN] is a variational quantum model that can potentially take multi-dimensional input.

The `QNN` class needs a circuit and a list of observables; the number of feature parameters in the input circuit determines the number of input features (i.e. the dimensionality of the classical data given as input) whereas the number of observables determines the number of outputs of the quantum neural network.

The circuit has two parts, the feature map and the ansatz. The feature map is responsible for encoding the input data into the quantum state, while the ansatz is responsible for the variational part of the model. In addition, a third part of the QNN is the observables, which is (a list of) operators that are measured at the end of the circuit.

In [QML Constructors](../../content/qml_constructors.md) we have seen how to construct the feature map and the ansatz. In this tutorial, we will see how to do the same using configs.

One convenient way to construct these three parts of the model is to use the config classes, namely, [`FeatureMapConfig`][qadence.ml_tools.config.FeatureMapConfig], [`AnsatzConfig`][qadence.ml_tools.config.AnsatzConfig], and [`ObservableConfig`][qadence.constructors.hamiltonians.ObservableConfig]. These classes allow you to specify the type of circuit and the parameters of the circuit in a structured way.

## Defining the Feature Map

Let us say we want to build a 4-qubit QNN that takes two inputs, namely, the $x$ and the $y$ coordinates of a point in the plane. We can use the `FeatureMapConfig` class to specify the feature map.

```python exec="on" source="material-block" session="config" html="1"
from qadence import BasisSet, chain, create_fm_blocks, FeatureMapConfig, ReuploadScaling

fm_config = FeatureMapConfig(
num_features=2,
inputs = ["x", "y"],
basis_set=BasisSet.CHEBYSHEV,
reupload_scaling=ReuploadScaling.TOWER,
feature_range={
"x": (-1.0, 1.0),
"y": (0.0, 1.0),
},
)

fm_blocks = create_fm_blocks(register=4, config=fm_config)
feature_map = chain(*fm_blocks)
from qadence.draw import html_string # markdown-exec: hide
print(html_string(feature_map)) # markdown-exec: hide
```

We have specified that the feature map should take two features, and have named the [`FeatureParameter`][qadence.parameters.FeatureParameter] "x" and "y" respectively. Both these parameters are encoded using the Chebyshev basis set, and the reupload scaling is set to `ReuploadScaling.TOWER`. One can optionally add the basis and the reupload scaling for each parameter separately.

The `feature_range` parameter is a dictionary that specifies the range of values that each feature comes from. This is useful for scaling the input data to the range that the encoding function can handle. In default case, this range is mapped to the target range of the Chebyshev basis set which is $[-1, 1]$. One can also specify the target range for each feature separately.

For full details on the `FeatureMapConfig` class, see the [API documentation][qadence.ml_tools.config.FeatureMapConfig].

## Defining the Ansatz

The next part of the QNN is the ansatz. We use `AnsatzConfig` class to specify the type of ansatz.

Let us say, we want to follow this feature map with 2 layers of hardware efficient ansatz.

```python exec="on" source="material-block" session="config" html="1"
from qadence import AnsatzConfig, AnsatzType, create_ansatz, Strategy

ansatz_config = AnsatzConfig(
depth=2,
ansatz_type=AnsatzType.HEA,
ansatz_strategy=Strategy.DIGITAL,
)

ansatz = create_ansatz(register=4, config=ansatz_config)

print(html_string(ansatz)) # markdown-exec: hide
```

We have specified that the ansatz should have a depth of 2, and the ansatz type is "hea" (Hardware Efficient Ansatz). The ansatz strategy is set to "digital", which means digital gates are being used. One could alternatively use "analog" or "rydberg" as the ansatz strategy.

For full details on the `AnsatzConfig` class, see the [API documentation][qadence.ml_tools.config.AnsatzConfig].

## Defining the Observable

And lastly, the observable. Naturally, we use the `ObservableConfig` class to specify the observable.

We can specify any Hamiltonian that we want to measure at the end of the circuit. Let us say we want to measure the $Z$ operator.

```python exec="on" source="material-block" session="config" html="1"
from qadence import observable_from_config, ObservableConfig, Z

observable_config = ObservableConfig(
detuning=Z,
scale=3.0,
shift=-1.0,
)

observable = observable_from_config(register=4, config=observable_config)
print(html_string(observable)) # markdown-exec: hide
```

We have specified the observable Hamiltonian to be one with $Z$-detuning. The result is linearly scaled by 3.0 and shifted by -1.0. These parameters can optionally also be [FeatureParameter][qadence.parameters.FeatureParameter] or [VariationalParameter][qadence.parameters.VariationalParameter]

One can also specify the observable as a list of observables, in which case the QNN will output a list of values.

For full details on the `ObservableConfig` class, see the [API documentation][qadence.constructors.hamiltonians.ObservableConfig].

## Defining the QNN from the Configs

To build the QNN, we can now use the `QNN` class.

```python exec="on" source="material-block" session="config" html="1"
from qadence import QNN

qnn = QNN.from_configs(
register=4,
fm_config=fm_config,
ansatz_config=ansatz_config,
obs_config=observable_config,
)

print(html_string(qnn)) # markdown-exec: hide
```
4 changes: 2 additions & 2 deletions docs/tutorials/qml/ml_tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ import matplotlib.pyplot as plt

from qadence import Parameter, QuantumCircuit, Z
from qadence import hamiltonian_factory, hea, feature_map, chain
from qadence.models import QNN
from qadence import QNN
from qadence.ml_tools import TrainConfig, train_with_grad, to_dataloader, DictDataLoader

DEVICE = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
Expand Down Expand Up @@ -195,7 +195,7 @@ import torch
from itertools import count
from qadence.constructors import hamiltonian_factory, hea, feature_map
from qadence import chain, Parameter, QuantumCircuit, Z
from qadence.models import QNN
from qadence import QNN
from qadence.ml_tools import TrainConfig

n_qubits = 2
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/qml/qcl.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ x_test, y_test = x[test_ind], y[test_ind]

## Train the QCL model

Qadence provides the [`QNN`][qadence.models.qnn.QNN] convenience constructor to build a quantum neural network.
Qadence provides the [`QNN`][qadence.ml_tools.models.QNN] convenience constructor to build a quantum neural network.
The `QNN` class needs a circuit and a list of observables; the number of feature parameters in the input circuit
determines the number of input features (i.e. the dimensionality of the classical data given as input) whereas
the number of observables determines the number of outputs of the quantum neural network.
Expand Down
3 changes: 2 additions & 1 deletion examples/quick_start.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

import torch

from qadence import QuantumModel # quantum model for execution

# qadence has many submodules
from qadence.blocks import kron # block system
from qadence.circuit import QuantumCircuit # circuit to assemble quantum operations
from qadence.logger import get_script_logger # Extend Qadence logging to your scripts
from qadence.ml_tools import TrainConfig, train_with_grad # tools for ML simulations
from qadence.models import QuantumModel # quantum model for execution
from qadence.operations import RX, HamEvo, X, Y, Zero # quantum operations
from qadence.parameters import VariationalParameter # trainable parameters

Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ nav:
- Variational quantum algorithms:
- tutorials/qml/index.md
- Training tools: tutorials/qml/ml_tools.md
- Configuring a QNN: tutorials/qml/config_qnn.md
- Quantum circuit learning: tutorials/qml/qcl.md
- Solving MaxCut with QAOA: tutorials/qml/qaoa.md
- Solving a 1D ODE: tutorials/qml/dqc_1d.md
Expand Down
Loading

0 comments on commit 6ad3ef5

Please sign in to comment.