lambeq.ansatz

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

Bases: abc.ABC

Base class for ansatz.

abstract __call__(diagram: discopy.rigid.Diagram) discopy.monoidal.Diagram[source]

Convert a DisCoPy diagram into a DisCoPy circuit or tensor.

abstract __init__(ob_map: Mapping[rigid.Ty, monoidal.Ty]) None[source]

Instantiate an ansatz.

Parameters
ob_mapdict

A mapping from discopy.rigid.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: Mapping[Ty, int], n_layers: int, n_single_qubit_params: int, circuit: Callable[[int, np.ndarray], Circuit], discard: bool = False, single_qubit_rotations: Optional[list[Circuit]] = None, postselection_basis: Circuit = Id(1))[source]

Bases: lambeq.ansatz.base.BaseAnsatz

Base class for circuit ansatz.

__call__(diagram: discopy.rigid.Diagram) discopy.quantum.circuit.Circuit[source]

Convert a DisCoPy diagram into a DisCoPy circuit.

__init__(ob_map: Mapping[Ty, int], n_layers: int, n_single_qubit_params: int, circuit: Callable[[int, np.ndarray], Circuit], discard: bool = False, single_qubit_rotations: Optional[list[Circuit]] = None, postselection_basis: Circuit = Id(1)) None[source]

Instantiate a circuit ansatz.

Parameters
ob_mapdict

A mapping from discopy.rigid.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.

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: discopy.rigid.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: lambeq.ansatz.circuit.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.

__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 discopy.rigid.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.

discardbool, default: False

Discard open wires instead of post-selecting.

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: lambeq.ansatz.tensor.TensorAnsatz

Split large boxes into matrix product states.

BOND_TYPE: discopy.rigid.Ty = Ty('B')
__call__(diagram: discopy.rigid.Diagram) discopy.tensor.Diagram[source]

Convert a DisCoPy diagram into a DisCoPy 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 discopy.rigid.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: lambeq.ansatz.circuit.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/pdf/1905.10876.pdf

__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 discopy.rigid.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.

discardbool, default: False

Discard open wires instead of post-selecting.

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: lambeq.ansatz.circuit.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/pdf/1905.10876.pdf

__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 discopy.rigid.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.

discardbool, default: False

Discard open wires instead of post-selecting.

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: lambeq.ansatz.tensor.TensorAnsatz

Split large boxes into spiders.

__call__(diagram: discopy.rigid.Diagram) discopy.tensor.Diagram[source]

Convert a DisCoPy diagram into a DisCoPy tensor.

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

Instantiate a spider ansatz.

Parameters
ob_mapdict

A mapping from discopy.rigid.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: Optional[list[int]] = None, discard: bool = False)[source]

Bases: lambeq.ansatz.circuit.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: Optional[list[int]] = None, discard: bool = False) None[source]

Instantiate a strongly entangling ansatz.

Parameters
ob_mapdict

A mapping from discopy.rigid.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.

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: numpy.ndarray) discopy.quantum.circuit.Circuit[source]
params_shape(n_qubits: int) tuple[int, ...][source]

Calculate the shape of the parameters required.

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

Bases: sympy.core.symbol.Symbol

A sympy symbol augmented with extra information.

Attributes
sizeint

The size of the tensor that this symbol represents.

default_assumptions = {}
name: str
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: lambeq.ansatz.base.BaseAnsatz

Base class for tensor network ansatz.

__call__(diagram: discopy.rigid.Diagram) discopy.tensor.Diagram[source]

Convert a DisCoPy diagram into a DisCoPy tensor.

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

Instantiate a tensor network ansatz.

Parameters
ob_mapdict

A mapping from discopy.rigid.Ty to the dimension space it uses in a tensor network.