Skip to content

Commit c4e361a

Browse files
ianyfanThomas HoffmannDimitri KartsaklisnikhilkhatriCharles London
committed
Release version 0.2.7
Co-authored-by: Thomas Hoffmann <thomas.hoffmann@cambridgequantum.com> Co-authored-by: Dimitri Kartsaklis <dimitri.kartsaklis@cambridgequantum.com> Co-authored-by: Nikhil Khatri <nikhil.khatri@quantinuum.com> Co-authored-by: Charles London <charles.london@cambridgequantum.com> Co-authored-by: Richie Yeung <richie.yeung@cambridgequantum.com>
1 parent d911686 commit c4e361a

File tree

94 files changed

+2672
-8135
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+2672
-8135
lines changed

.github/workflows/build_test.yml

+25-26
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,6 @@ jobs:
5454
uses: actions/setup-python@v2
5555
with:
5656
python-version: ${{ matrix.python-version }}
57-
- name: Determine if depccg tests should be run
58-
# only test depccg if it is explicitly changed, since it is very slow
59-
# (also ignore it on 3.10 because it doesn't install properly)
60-
id: depccg-enabled
61-
continue-on-error: true # this is expected to fail but the job should still succeed
62-
run: >
63-
${{ matrix.python-version != '3.10' }}
64-
&& git fetch --depth=1 origin ${{ github.base_ref || github.event.before }}:before
65-
&& git diff --name-only before | grep depccg
6657
- name: Locate pip cache
6758
id: loc-pip-cache
6859
run: echo "::set-output name=dir::$(pip cache dir)"
@@ -83,23 +74,6 @@ jobs:
8374
run: python -c 'import lambeq'
8475
- name: Install extra dependencies and tester
8576
run: pip install .[extras] .[test]
86-
- name: Install depccg and locate depccg pre-trained model cache
87-
id: loc-depccg-cache
88-
if: steps.depccg-enabled.outcome == 'success'
89-
run: |
90-
pip install cython # must be installed before depccg
91-
pip install depccg==2.0.3.2
92-
echo "::set-output name=dir::$(python -c 'from depccg.instance_models import MODEL_DIRECTORY, MODELS; print(MODEL_DIRECTORY / MODELS["en"][1])')"
93-
- name: Restore depccg pre-trained model from cache
94-
id: depccg-cache
95-
if: steps.depccg-enabled.outcome == 'success'
96-
uses: actions/cache@v2
97-
with:
98-
path: ${{ steps.loc-depccg-cache.outputs.dir }}
99-
key: depccg
100-
- name: Download depccg pre-trained model if needed
101-
if: steps.depccg-cache.outputs.cache-hit == 'false'
102-
run: python -c 'import tarfile, urllib;from depccg.instance_models import MODEL_DIRECTORY;tarfile.open(urllib.request.urlretrieve("https://qnlp.cambridgequantum.com/models/tri_headfirst.tar.gz")[0]).extractall(MODEL_DIRECTORY)'
10377
- name: Locate bobcat pre-trained model cache
10478
id: loc-bobcat-cache
10579
run: echo "::set-output name=dir::$(python -c 'from lambeq.text2diagram.bobcat_parser import get_model_dir; print(get_model_dir("bert"))')"
@@ -117,6 +91,31 @@ jobs:
11791
--durations=50
11892
--ignore=${{ env.TEST_DIR }}/text2diagram/test_depccg_parser.py
11993
--ignore=docs/extract_code_cells.py
94+
- name: Determine if depccg tests should be run
95+
# only test depccg if it is explicitly changed, since it is very slow
96+
id: depccg-enabled
97+
continue-on-error: true # this is expected to fail but the job should still succeed
98+
run: >
99+
git fetch --depth=1 origin ${{ github.base_ref || github.event.before }}:before
100+
&& git diff --name-only before | grep depccg
101+
- name: Install depccg and locate depccg pre-trained model cache
102+
id: loc-depccg-cache
103+
if: steps.depccg-enabled.outcome == 'success'
104+
run: |
105+
pip install cython # must be installed before depccg
106+
pip install depccg==2.0.3.2
107+
echo "::set-output name=dir::$(python -c 'from depccg.instance_models import MODEL_DIRECTORY, MODELS; print(MODEL_DIRECTORY / MODELS["en"][1])')"
108+
pip install lambeq # override dependency conflicts
109+
- name: Restore depccg pre-trained model from cache
110+
id: depccg-cache
111+
if: steps.depccg-enabled.outcome == 'success'
112+
uses: actions/cache@v2
113+
with:
114+
path: ${{ steps.loc-depccg-cache.outputs.dir }}
115+
key: depccg
116+
- name: Download depccg pre-trained model if needed
117+
if: steps.depccg-cache.outputs.cache-hit == 'false'
118+
run: python -c 'import tarfile, urllib;from depccg.instance_models import MODEL_DIRECTORY;tarfile.open(urllib.request.urlretrieve("https://qnlp.cambridgequantum.com/models/tri_headfirst.tar.gz")[0]).extractall(MODEL_DIRECTORY)'
120119
- name: Test DepCCGParser
121120
if: steps.depccg-enabled.outcome == 'success'
122121
continue-on-error: true

docs/_static/css/table-wrap.css

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/* override table no-wrap */
2+
.wy-table-responsive table td, .wy-table-responsive table th {
3+
white-space: normal;
4+
}
5+
table.docutils div.line-block {
6+
margin-bottom: 0;
7+
}
8+
-114 KB
Binary file not shown.
-536 KB
Binary file not shown.
-33.4 KB
Binary file not shown.
-158 KB
Binary file not shown.
-169 KB
Binary file not shown.
-438 KB
Binary file not shown.
-148 KB
Binary file not shown.
-479 KB
Binary file not shown.

docs/_static/images/use_cases.png

79.7 KB
Loading

docs/conf.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@
4646
]
4747

4848
intersphinx_mapping = {
49-
'discopy': ("https://discopy.readthedocs.io/en/main/", None)
49+
'discopy': ("https://discopy.readthedocs.io/en/main/", None),
50+
'pennylane': ("https://pennylane.readthedocs.io/en/stable/", None),
5051
}
5152

5253
autodoc_default_options = {
@@ -74,6 +75,9 @@
7475
# a list of builtin themes.
7576
#
7677
html_theme = 'sphinx_rtd_theme'
78+
html_theme_options = {
79+
'navigation_depth': -1
80+
}
7781
html_context = {
7882
'display_github': True,
7983
'github_user': 'CQCL',
@@ -89,6 +93,10 @@
8993
html_logo = '_static/images/lambeq_logo.png'
9094
html_favicon = '_static/images/favicon.ico'
9195

96+
# CSS for allowing text wrapping within table cells
97+
html_css_files = [
98+
'css/table-wrap.css',
99+
]
92100

93101
def autodoc_skip_member(app, what, name, obj, skip, options):
94102
if name == 'Symbol':

docs/examples/classical_pipeline.ipynb

+1-3
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@
3333
},
3434
{
3535
"cell_type": "markdown",
36-
"metadata": {
37-
"tags": []
38-
},
36+
"metadata": {},
3937
"source": [
4038
"### Input data"
4139
]

docs/glossary.rst

+19-1
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,31 @@ Glossary
7171
natural language processing (NLP)
7272
The use of computational methods for solving language-related problems.
7373

74+
NISQ
75+
Noisy Intermediate-Scale Quantum. A term for characterising the current state of quantum hardware, where quantum processors still contain a small number of qubits, and are not advanced enough to reach fault-tolerance nor large enough to profit substantially from quantum supremacy.
76+
77+
noise
78+
Undesired artefacts that cause the measurement outcome of a :term:`quantum circuit` to deviate from the ideal distribution.
79+
7480
parser
7581
A statistical tool that converts a sentence into a hierarchical representation that reflects the syntactic relationships between the words (a :term:`syntax tree`) based on a specific grammar formalism.
7682

83+
PennyLane
84+
A Python library for differentiable programming of quantum computers, developed by Xanadu, enabling quantum machine learning.
85+
86+
post-selection
87+
The act of conditioning the probability space on a particular event. In practice, this involves disregarding measurement outcomes where a particular qubit does not match the post-selected value.
88+
7789
pregroup grammar
7890
A grammar formalism developed by Joachim Lambek in 1999 [Lam1999]_ based on the notion of a *pregroup*. Pregroup grammars are closely related to categorial grammars (such as :term:`CCG <Combinatory Categorial Grammar (CCG)>`). In category-theoretic terms, a pregroup grammar forms a :term:`rigid category`, sometimes also referred to as a non-symmetric :term:`compact closed category`.
7991

8092
pytket
8193
A Python interface for the :term:`tket` compiler.
8294

83-
qiskit
95+
PyTorch
96+
An open source machine learning framework primarily developed by Meta AI.
97+
98+
Qiskit
8499
An open-source SDK developed by IBM Research for working with quantum computers at the level of circuits, pulses, and algorithms.
85100

86101
quantum circuit
@@ -104,6 +119,9 @@ Glossary
104119
rigid category
105120
A :term:`monoidal category` where every object :math:`A` has a left dual :math:`A^l` and a right dual :math:`A^r`, both equipped with :term:`cup` and :term:`cap` morphisms obeying the so-called :term:`snake equations`. A :term:`pregroup grammar` is an example of a rigid category.
106121

122+
shots
123+
A collection of measurement outcomes from a particular :term:`quantum circuit`.
124+
107125
snake equations
108126
Identities that hold between the dual objects of a :term:`monoidal category` and allow the "yanking" of wires and the rewriting and simplification of diagrams. In ``lambeq`` and :term:`DisCoPy`, the :py:meth:`monoidal.Diagram.normal_form() <discopy.monoidal.Diagram.normal_form>` method uses the snake equations in order to "stretch" the wires of a diagram and provide a normal form for it.
109127

docs/index.rst

+2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ If you use ``lambeq`` for your research, please cite the accompanying paper [Kea
5151
parsing
5252
string_diagrams
5353
discopy
54+
use-cases
5455
CONTRIBUTING
5556

5657
.. toctree::
@@ -61,6 +62,7 @@ If you use ``lambeq`` for your research, please cite the accompanying paper [Kea
6162
../tutorials/rewrite.ipynb
6263
../tutorials/parameterise.ipynb
6364
training
65+
models
6466
manual_training
6567
advanced
6668
../tutorials/extend-lambeq.ipynb

docs/models.rst

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
.. _sec-models:
2+
3+
Choosing a model
4+
================
5+
6+
The following sections provide more information on the various models.
7+
8+
.. _sec-numpymodel:
9+
10+
NumpyModel
11+
----------
12+
13+
A :py:class:`.NumpyModel` uses the unitary and density matrix simulators in DisCoPy, which convert quantum circuits into a tensor network. The resulting tensor network is efficiently contracted using ``opt_einsum``.
14+
15+
Circuits containing only :py:class:`Bra <discopy.quantum.gates.Bra>`, :py:class:`Ket <discopy.quantum.gates.Ket>` and unitary gates are evaluated using DisCoPy's unitary simulator, while circuits containing :py:class:`Encode <discopy.quantum.circuit.Encode>`, :py:class:`Measure <discopy.quantum.circuit.Measure>` or :py:class:`Discard <discopy.quantum.circuit.Discard>` are evaluated using DisCoPy's density matrix simulator.
16+
17+
.. note::
18+
19+
Note that the unitary simulator converts a circuit with ``n`` output qubits into a tensor of shape ``(2, ) * n``, while the density matrix simulator converts a circuit with ``n`` output qubits and ``m`` output bits into a tensor of shape ``(2, ) * (2 * n + m)``.
20+
21+
In the common use case of using a :py:data:`~lambeq.text2diagram.stairs_reader` or a :py:class:`.TreeReader` with discarding for binary classification, the process involves measuring (:py:class:`Measure <discopy.quantum.circuit.Measure>`) one of the "open" qubits, and discarding (:py:class:`Discard <discopy.quantum.circuit.Discard>`) the rest of them.
22+
23+
One advantage that the :py:class:`.NumpyModel` has over the :py:class:`.TketModel` is that it supports the just-in-time (jit) compilation provided by the library ``jax``. This speeds up the model's diagram evaluation by an order of magnitude. The :py:class:`.NumpyModel` with ``jit`` mode enabled can be instantiated with the following command:
24+
25+
.. code-block:: python
26+
27+
from lambeq import NumpyModel
28+
29+
model = NumpyModel.from_diagrams(circuits, use_jit=True)
30+
31+
.. note::
32+
Using the :py:class:`.NumpyModel` with ``jit`` mode enabled is not recommended for large models, as it requires a large amount of memory to store the pre-compiled functions for each circuit.
33+
34+
To use the :py:class:`.NumpyModel` with ``jit`` mode, you need to install ``lambeq`` with the extra packages by running the following command:
35+
36+
.. code-block:: bash
37+
38+
pip install lambeq[extras]
39+
40+
.. note::
41+
42+
To enable GPU support for ``jax``, follow the installation instructions on the `JAX GitHub repository <https://github.com/google/jax#installation>`_.
43+
44+
:py:class:`.NumpyModel` should be used with the :py:class:`.QuantumTrainer`.
45+
46+
.. rubric:: See also the following use cases:
47+
48+
- :ref:`uc1`
49+
50+
.. _sec-pytorchmodel:
51+
52+
PytorchModel
53+
------------
54+
55+
:py:class:`.PytorchModel` is the right choice for classical experiments. Here, string diagrams are treated as tensor networks, where boxes represent tensors and edges define the specific tensor contractions. Tensor contractions are optimised by the python package ``opt_einsum``.
56+
57+
To prepare the diagrams for the computation, we use a :py:class:`.TensorAnsatz` that converts a rigid diagram into a tensor diagram. Subclasses of :py:class:`.TensorAnsatz` include the :py:class:`.SpiderAnsatz` and the :py:class:`.MPSAnsatz`, which reduce the size of large tensors by spliting them into chains of many smaller boxes. To prepare a tensor diagram for a sentence, for example:
58+
59+
.. code-block:: python
60+
61+
from lambeq import AtomicType, BobcatParser, TensorAnsatz
62+
from discopy import Dim
63+
64+
parser = BobcatParser()
65+
rigid_diagram = parser.sentence2diagram('This is a tensor network.')
66+
67+
ansatz = TensorAnsatz({AtomicType.NOUN: Dim(2), AtomicType.SENTENCE: Dim(4)})
68+
tensor_diagram = ansatz(rigid_diagram)
69+
70+
After preparing a list of tensor diagrams, we can initialise the model through:
71+
72+
.. code-block:: python
73+
74+
from lambeq import PytorchModel
75+
76+
model = PytorchModel.from_diagrams(tensor_diagrams)
77+
78+
The :py:class:`.PytorchModel` is capable of combining tensor networks and neural network architectures. For example, it is possible to feed the output of a tensor diagram into a neural network, by subclassing and modifying the :py:meth:`~lambeq.PytorchModel.forward` method:
79+
80+
.. code-block:: python
81+
82+
import torch
83+
from lambeq import PytorchModel
84+
85+
class MyCustomModel(PytorchModel):
86+
def __init__(self):
87+
super().__init__()
88+
self.net = torch.nn.Linear(2, 2)
89+
90+
def forward(self, input):
91+
"""define a custom forward pass here"""
92+
preds = self.get_diagram_output(input) # performs tensor contraction
93+
return self.net(preds)
94+
95+
To simplify training, the :py:class:`.PytorchModel` can be used with the :py:class:`.PytorchTrainer`. A comprehensive tutorial can be found `here <tutorials/trainer_classical.ipynb>`_.
96+
97+
.. note::
98+
99+
The loss function and the accuracy metric in the tutorial are defined for two-dimensional binary labels: ``[[1,0], [0,1], ...]``. If your data has a different structure, you must implement your custom loss function and evaluation metrics.
100+
101+
.. rubric:: See also the following use cases:
102+
103+
- :ref:`uc4`
104+
105+
.. _sec-tketmodel:
106+
107+
TketModel
108+
---------
109+
110+
:py:class:`.TketModel` uses ``pytket`` to retrieve shot-based results from a quantum computer, then uses the shot counts to build the resulting tensor.
111+
112+
The ``AerBackend`` can be used with :py:class:`.TketModel` to perform a noisy, architecture-aware simulation of an IBM machine. Other backends supported by ``pytket`` can also be used. To run an experiment on a real quantum computer, for example:
113+
114+
.. code-block:: python
115+
116+
from lambeq import TketModel
117+
from pytket.extensions.quantinuum import QuantinuumBackend
118+
119+
machine = 'H1-1E'
120+
backend = QuantinuumBackend(device_name=machine)
121+
backend.login()
122+
123+
backend_config = {
124+
'backend': backend,
125+
'compilation': backend.default_compilation_pass(2),
126+
'shots': 2048
127+
}
128+
129+
model = TketModel.from_diagrams(all_circuits, backend_config=backend_config)
130+
131+
.. note::
132+
133+
Note that you need user accounts and allocated resources to run experiments on real machines. However, `IBM Quantum <https://quantum-computing.ibm.com/>`_ provides some limited resources for free.
134+
135+
For initial experiments we recommend using a :py:class:`.NumpyModel`, as it performs noiseless simulations and is orders of magnitude faster.
136+
137+
:py:class:`.TketModel` should be used with the :py:class:`.QuantumTrainer`.
138+
139+
.. rubric:: See also the following use cases:
140+
141+
- :ref:`uc2`
142+
- :ref:`uc3`

docs/puml/ansatz.puml

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
@startuml
2+
3+
set namespaceseparator none
4+
skinparam dpi 96
5+
skinparam shadowing true
6+
skinparam ArrowColor Black
7+
skinparam class {
8+
backgroundColor Business
9+
borderColor Red
10+
}
11+
12+
abstract class BaseAnsatz {
13+
ob_map: dict
14+
}
15+
class TensorAnsatz {
16+
ob_map: Mapping[Ty, Dim]
17+
functor
18+
}
19+
class CircuitAnsatz {
20+
functor
21+
ob_map: Mapping[Ty, int]
22+
}
23+
class MPSAnsatz {
24+
BOND_TYPE
25+
bond_dim: int
26+
max_order: int
27+
split_functor
28+
tensor_functor
29+
}
30+
class SpiderAnsatz {
31+
max_order: int
32+
split_functor
33+
tensor_functor
34+
}
35+
class IQPAnsatz {
36+
discard: bool
37+
functor
38+
n_layers: int
39+
n_single_qubit_params: int
40+
}
41+
class Symbol {
42+
size: int
43+
sort_key(order)
44+
}
45+
class sympy.core.symbol.Symbol #back:wheat;line:tomato {}
46+
47+
class discopy.rigid.Ty #back:lightblue;line:black {}
48+
class discopy.rigid.Ob #back:lightblue;line:black {}
49+
class discopy.rigid.Functor #back:lightblue;line:black {}
50+
class discopy.quantum.circuit.Functor #back:lightblue;line:black {}
51+
class discopy.monoidal.Ty #back:lightblue;line:black {}
52+
53+
discopy.rigid.Ob <|-- discopy.rigid.Ty
54+
discopy.rigid.Functor <|-- discopy.quantum.circuit.Functor
55+
56+
BaseAnsatz <|-- TensorAnsatz
57+
BaseAnsatz <|-- CircuitAnsatz
58+
TensorAnsatz <|-- MPSAnsatz
59+
TensorAnsatz <|-- SpiderAnsatz
60+
CircuitAnsatz <|-- IQPAnsatz
61+
discopy.monoidal.Ty <|-- discopy.rigid.Ty
62+
63+
MPSAnsatz::split_functor *-left- discopy.rigid.Functor
64+
MPSAnsatz::tensor_functor *-- discopy.rigid.Functor
65+
SpiderAnsatz::split_functor *-- discopy.rigid.Functor
66+
SpiderAnsatz::tensor_functor *-- discopy.rigid.Functor
67+
MPSAnsatz::BOND_TYPE *--left discopy.rigid.Ty
68+
CircuitAnsatz::functor *-- discopy.quantum.circuit.Functor
69+
TensorAnsatz::functor *-- discopy.quantum.circuit.Functor
70+
IQPAnsatz::functor *-- discopy.quantum.circuit.Functor
71+
sympy.core.symbol.Symbol <|-- Symbol
72+
73+
@enduml

0 commit comments

Comments
 (0)