lambeq.ansatz

class lambeq.ansatz.BaseAnsatz(ob_map: Mapping[Ty, Dim])[source]

Bases: ABC

Base class for ansatz.

abstract __call__(diagram: Diagram) Diagram[source]

Convert a diagram into a circuit or tensor.

abstract __init__(ob_map: Mapping[Ty, Dim]) None[source]

Instantiate an ansatz.

Parameters:
ob_mapdict

A mapping from lambeq.backend.grammar.Ty to a type in the target category. In the category of quantum circuits, this type is the number of qubits; in the category of vector spaces, this type is a vector space.

class lambeq.ansatz.CircuitAnsatz(ob_map: ~collections.abc.Mapping[~lambeq.backend.grammar.Ty, int], n_layers: int, n_single_qubit_params: int, circuit: ~collections.abc.Callable[[int, ~numpy.ndarray], ~lambeq.backend.quantum.Diagram], discard: bool = False, single_qubit_rotations: list[~typing.Type[~lambeq.backend.quantum.Rotation]] | None = None, postselection_basis: ~lambeq.backend.quantum.Diagram = Diagram(dom=Ty(qubit), cod=Ty(qubit), layers=[], __hash__=<function Diagram.__hash__>))[source]

Bases: BaseAnsatz

Base class for circuit ansatz.

__call__(diagram: Diagram) Diagram[source]

Convert a lambeq diagram into a lambeq circuit.

__init__(ob_map: ~collections.abc.Mapping[~lambeq.backend.grammar.Ty, int], n_layers: int, n_single_qubit_params: int, circuit: ~collections.abc.Callable[[int, ~numpy.ndarray], ~lambeq.backend.quantum.Diagram], discard: bool = False, single_qubit_rotations: list[~typing.Type[~lambeq.backend.quantum.Rotation]] | None = None, postselection_basis: ~lambeq.backend.quantum.Diagram = Diagram(dom=Ty(qubit), cod=Ty(qubit), layers=[], __hash__=<function Diagram.__hash__>)) None[source]

Instantiate a circuit ansatz.

Parameters:
ob_mapdict

A mapping from lambeq.backend.grammar.Ty to the number of qubits it uses in a circuit.

n_layersint

The number of layers used by the ansatz.

n_single_qubit_paramsint

The number of single qubit rotations used by the ansatz. It only affects wires that ob_map maps to a single qubit.

circuitcallable

Circuit generator used by the ansatz. This is a function (or a class constructor) that takes a number of qubits and a numpy array of parameters, and returns the ansatz of that size, with parameterised boxes.

discardbool, default: False

Discard open wires instead of post-selecting.

postselection_basis: Circuit, default: Id(qubit)

Basis to post-select in, by default the computational basis.

single_qubit_rotations: list of Circuit, optional

The rotations to be used for a single qubit. When only a single qubit is present, the ansatz defaults to applying a series of rotations in a cycle, determined by this parameter and n_single_qubit_params.

ob_size(pg_type: Ty) int[source]

Calculate the number of qubits used for a given type.

abstract params_shape(n_qubits: int) tuple[int, ...][source]

Calculate the shape of the parameters required.

class lambeq.ansatz.IQPAnsatz(ob_map: Mapping[Ty, int], n_layers: int, n_single_qubit_params: int = 3, discard: bool = False)[source]

Bases: CircuitAnsatz

Instantaneous Quantum Polynomial ansatz.

An IQP ansatz interleaves layers of Hadamard gates with diagonal unitaries. This class uses n_layers-1 adjacent CRz gates to implement each diagonal unitary.

Code adapted from DisCoPy.

__init__(ob_map: Mapping[Ty, int], n_layers: int, n_single_qubit_params: int = 3, discard: bool = False) None[source]

Instantiate an IQP ansatz.

Parameters:
ob_mapdict

A mapping from lambeq.backend.grammar.Ty to the number of qubits it uses in a circuit.

n_layersint

The number of layers used by the ansatz.

n_single_qubit_paramsint, default: 3

The number of single qubit rotations used by the ansatz. It only affects wires that ob_map maps to a single qubit.

discardbool, default: False

Discard open wires instead of post-selecting.

circuit(n_qubits: int, params: ndarray) Diagram[source]
params_shape(n_qubits: int) tuple[int, ...][source]

Calculate the shape of the parameters required.

class lambeq.ansatz.MPSAnsatz(ob_map: Mapping[Ty, Dim], bond_dim: int, max_order: int = 3)[source]

Bases: TensorAnsatz

Split large boxes into matrix product states.

BOND_TYPE: Ty = Ty(B)
__call__(diagram: Diagram) Diagram[source]

Convert a diagram into a tensor.

__init__(ob_map: Mapping[Ty, Dim], bond_dim: int, max_order: int = 3) None[source]

Instantiate a matrix product state ansatz.

Parameters:
ob_mapdict

A mapping from lambeq.backend.grammar.Ty to the dimension space it uses in a tensor network.

bond_dim: int

The size of the bonding dimension.

max_order: int

The maximum order of each tensor in the matrix product state, which must be at least 3.

class lambeq.ansatz.Sim14Ansatz(ob_map: Mapping[Ty, int], n_layers: int, n_single_qubit_params: int = 3, discard: bool = False)[source]

Bases: CircuitAnsatz

Modification of circuit 14 from Sim et al.

Replaces circuit-block construction with two rings of CRx gates, in opposite orientation.

Paper at: https://arxiv.org/abs/1905.10876

Code adapted from DisCoPy.

__init__(ob_map: Mapping[Ty, int], n_layers: int, n_single_qubit_params: int = 3, discard: bool = False) None[source]

Instantiate a Sim 14 ansatz.

Parameters:
ob_mapdict

A mapping from lambeq.backend.grammar.Ty to the number of qubits it uses in a circuit.

n_layersint

The number of layers used by the ansatz.

n_single_qubit_paramsint, default: 3

The number of single qubit rotations used by the ansatz. It only affects wires that ob_map maps to a single qubit.

discardbool, default: False

Discard open wires instead of post-selecting.

circuit(n_qubits: int, params: ndarray) Diagram[source]
params_shape(n_qubits: int) tuple[int, ...][source]

Calculate the shape of the parameters required.

class lambeq.ansatz.Sim15Ansatz(ob_map: Mapping[Ty, int], n_layers: int, n_single_qubit_params: int = 3, discard: bool = False)[source]

Bases: CircuitAnsatz

Modification of circuit 15 from Sim et al.

Replaces circuit-block construction with two rings of CNOT gates, in opposite orientation.

Paper at: https://arxiv.org/abs/1905.10876

Code adapted from DisCoPy.

__init__(ob_map: Mapping[Ty, int], n_layers: int, n_single_qubit_params: int = 3, discard: bool = False) None[source]

Instantiate a Sim 15 ansatz.

Parameters:
ob_mapdict

A mapping from lambeq.backend.grammar.Ty to the number of qubits it uses in a circuit.

n_layersint

The number of layers used by the ansatz.

n_single_qubit_paramsint, default: 3

The number of single qubit rotations used by the ansatz. It only affects wires that ob_map maps to a single qubit.

discardbool, default: False

Discard open wires instead of post-selecting.

circuit(n_qubits: int, params: ndarray) Diagram[source]
params_shape(n_qubits: int) tuple[int, ...][source]

Calculate the shape of the parameters required.

class lambeq.ansatz.Sim4Ansatz(ob_map: Mapping[Ty, int], n_layers: int, n_single_qubit_params: int = 3, discard: bool = False)[source]

Bases: CircuitAnsatz

Circuit 4 from Sim et al.

Ansatz with a layer of Rx and Rz gates, followed by a ladder of CRxs.

Paper at: https://arxiv.org/abs/1905.10876

__init__(ob_map: Mapping[Ty, int], n_layers: int, n_single_qubit_params: int = 3, discard: bool = False) None[source]

Instantiate a Sim 4 ansatz.

Parameters:
ob_mapdict

A mapping from lambeq.backend.grammar.Ty to the number of qubits it uses in a circuit.

n_layersint

The number of layers used by the ansatz.

n_single_qubit_paramsint, default: 3

The number of single qubit rotations used by the ansatz. It only affects wires that ob_map maps to a single qubit.

discardbool, default: False

Discard open wires instead of post-selecting.

circuit(n_qubits: int, params: ndarray) Diagram[source]
params_shape(n_qubits: int) tuple[int, ...][source]

Calculate the shape of the parameters required.

class lambeq.ansatz.SpiderAnsatz(ob_map: Mapping[Ty, Dim], max_order: int = 2)[source]

Bases: TensorAnsatz

Split large boxes into spiders.

__call__(diagram: Diagram) Diagram[source]

Convert a diagram into a tensor.

__init__(ob_map: Mapping[Ty, Dim], max_order: int = 2) None[source]

Instantiate a spider ansatz.

Parameters:
ob_mapdict

A mapping from lambeq.backend.grammar.Ty to the dimension space it uses in a tensor network.

max_order: int

The maximum order of each tensor, which must be at least 2.

class lambeq.ansatz.StronglyEntanglingAnsatz(ob_map: Mapping[Ty, int], n_layers: int, n_single_qubit_params: int = 3, ranges: list[int] | None = None, discard: bool = False)[source]

Bases: CircuitAnsatz

Strongly entangling ansatz.

Ansatz using three single qubit rotations (RzRyRz) followed by a ladder of CNOT gates with different ranges per layer.

This is adapted from the PennyLane implementation of the pennylane.StronglyEntanglingLayers, pursuant to Apache 2.0 licence.

The original paper which introduces the architecture can be found here.

__init__(ob_map: Mapping[Ty, int], n_layers: int, n_single_qubit_params: int = 3, ranges: list[int] | None = None, discard: bool = False) None[source]

Instantiate a strongly entangling ansatz.

Parameters:
ob_mapdict

A mapping from lambeq.backend.grammar.Ty to the number of qubits it uses in a circuit.

n_layersint

The number of circuit layers used by the ansatz.

n_single_qubit_paramsint, default: 3

The number of single qubit rotations used by the ansatz. It only affects wires that ob_map maps to a single qubit.

rangeslist of int, optional

The range of the CNOT gate between wires in each layer. By default, the range starts at one (i.e. adjacent wires) and increases by one for each subsequent layer.

discardbool, default: False

Discard open wires instead of post-selecting.

circuit(n_qubits: int, params: ndarray) Diagram[source]
params_shape(n_qubits: int) tuple[int, ...][source]

Calculate the shape of the parameters required.

class lambeq.ansatz.Symbol(name: str, directed_dom: int = 1, directed_cod: int = 1, **assumptions: bool)[source]

Bases: Symbol

A sympy symbol augmented with extra information.

Attributes:
directed_domint

The size of the domain of the tensor-box that this symbol represents.

directed_codint

The size of the codomain of the tensor-box that this symbol represents.

sizeint

The total size of the tensor that this symbol represents (directed_dom * directed_cod).

default_assumptions = {}
directed_cod: int
directed_dom: int
name: str
property size: int
sort_key(order: Literal[None] = None) tuple[Any, ...][source]

Return a sort key.

Examples

>>> from sympy import S, I
>>> sorted([S(1)/2, I, -I], key=lambda x: x.sort_key())
[1/2, -I, I]
>>> S("[x, 1/x, 1/x**2, x**2, x**(1/2), x**(1/4), x**(3/2)]")
[x, 1/x, x**(-2), x**2, sqrt(x), x**(1/4), x**(3/2)]
>>> sorted(_, key=lambda x: x.sort_key())
[x**(-2), 1/x, x**(1/4), sqrt(x), x, x**(3/2), x**2]
class lambeq.ansatz.TensorAnsatz(ob_map: Mapping[Ty, Dim])[source]

Bases: BaseAnsatz

Base class for tensor network ansatz.

__call__(diagram: Diagram) Diagram[source]

Convert a diagram into a tensor.

__init__(ob_map: Mapping[Ty, Dim]) None[source]

Instantiate a tensor network ansatz.

Parameters:
ob_mapdict

A mapping from lambeq.backend.grammar.Ty to the dimension space it uses in a tensor network.