Skip to content

configs

eigenkit.configs

The blocks that make up a circuit, and the configurations of the backends.

Blocks are combined into a circuit with Circuit(blocks=[...]):

  • Encoding encodes classical features as rotation angles.
  • Variational applies, in each layer, one trainable rotation to every qubit, followed by a ladder of controlled-NOT (CNOT) gates.
  • StrongVariational applies, in each layer, trainable RZ, RY and RZ rotations to every qubit, followed by a ladder of CNOT gates.
  • Reuploading encodes the input several times, between trainable layers. The encoding can have a trainable scale.

A configuration selects a backend and holds its settings. Pass it to Circuit(provider=...), or register a name for it. NumpyConfig is documented below, and the other configurations are documented with their backends:

The blocks and NumpyConfig are imported with this module, because they only need NumPy. The other configurations are imported when they are first used, so importing this module does not import PyTorch, PennyLane, Qiskit or Braket.

The quantities to measure are set with Circuit(observables=...). They are not a block.

Example
import numpy as np
from eigenkit import Circuit, all_z
from eigenkit.configs import Encoding, Variational, NumpyConfig

circuit = Circuit(
    blocks=[Encoding(in_features=3), Variational(depth=2)],
    observables=all_z(3),
    provider=NumpyConfig(),
)

print(circuit.spec.n_qubits, circuit.spec.n_weights)  # 3 6
print(circuit(np.zeros(circuit.spec.n_weights), np.zeros(3)))  # [1. 1. 1.]

To change the backend, you change one argument. provider=PennyLaneConfig(...) runs the same blocks on PennyLane, and provider="numpy" selects the same reference simulator by its registered name.

Encoding dataclass

Encode in_features data values as single-qubit rotations.

Feature i sets the angle of one rotation on qubit i, so the block uses the qubits 0 to in_features - 1. This matters only when the block is combined with others. A circuit has as many qubits as its widest block, and when another block in the list needs more qubits, this block leaves the extra qubits unchanged.

The block takes in_features inputs and no weights.

Parameters:

Name Type Description Default
in_features int

The number of features to encode, one per qubit. It must be positive, and a ValueError is raised otherwise.

required
rotation GateName

The rotation gate: "RX", "RY" or "RZ". Default: "RY".

'RY'
scale float

A constant factor applied to every input angle. It is useful when the data is normalised to [0, 1] and the circuit needs angles in [0, 2π]. It must be finite. Default: 1.0.

1.0

build(n_qubits)

Build the gates of this block for a circuit with n_qubits qubits.

The qubits with an index of in_features or more are left unchanged.

Parameters:

Name Type Description Default
n_qubits int

The number of qubits of the circuit being assembled, which is the number of qubits of the widest block in the list.

required

Returns:

Type Description
IRFragment

The gates of the block, as an IRFragment. Its weight and input indices start at 0, and they are shifted when the blocks are combined into a circuit.

from_dict(d) classmethod

Rebuild a block from the output of to_dict().

Parameters:

Name Type Description Default
d dict

A dictionary returned by to_dict().

required

Returns:

Type Description
'AngleEncoding'

The rebuilt AngleEncoding.

required_qubits()

Return in_features, because the block uses one qubit per feature.

to_dict()

Return a description of this block that can be saved as JSON.

When a saved model is loaded, the type key selects the block class whose from_dict() rebuilds the block.

Returns:

Type Description
dict

The fields of the block, and its type.

NumpyConfig dataclass

Configuration for the reference NumPy simulator.

It has no settings yet. It exists so that Circuit(provider=NumpyConfig()) works in the same way as with the configurations of the other backends.

make_backend()

Build the backend that this configuration describes.

The provider layer calls it when a configuration is passed as provider=. There is no reason to call it directly.

Returns:

Type Description
'NumpySimulator'

The NumpySimulator for this configuration.

Reuploading dataclass

Data reuploading: the input is encoded several times, between trainable layers.

The block repeats an encoding of the input followed by a variational layer, depth times. Each encoding can have a trainable scale for each feature and repetition.

The arguments give two patterns:

  1. Standard reuploading (the default; Pérez-Salinas et al. 2020). The same input is encoded depth times, with new variational weights between the encodings.
  2. Trainable feature scaling (trainable_scale=True; Schuld et al. 2021). Each encoding rotation takes the angle λ_{d,i} * x_i, where each pair of repetition d and feature i has its own trainable λ_{d,i}.

Parameters:

Name Type Description Default
in_features int

The total number of input features. It must be positive.

required
depth int

The number of times the whole sequence is repeated. It must be positive.

required
encoding_rotation GateName

The rotation gate of the encoding: "RX", "RY" or "RZ". Default: "RY".

'RY'
variational_rotation GateName

The rotation gate of the variational layer: "RX", "RY" or "RZ". It is used only when variational_type="basic". Default: "RY".

'RY'
variational_type str

"basic", for one rotation per qubit followed by a ladder of controlled-NOT (CNOT) gates, or "strong", for RZ, RY and RZ rotations on every qubit followed by a ladder of CNOT gates. Default: "basic".

'basic'
trainable_scale bool

If True, each encoding rotation gets a trainable scale for each repetition and each feature. The CUDA Quantum backend does not support it, because it allows only limited arithmetic on parameters. Default: False.

False
Weight count
  • With variational_type="basic" and no trainable scale, the block has depth * in_features weights.
  • With variational_type="strong" and no trainable scale, it has 3 * depth * in_features weights.
  • trainable_scale=True adds depth * in_features weights.

build(n_qubits)

Build the gates of this block for a circuit with n_qubits qubits.

Parameters:

Name Type Description Default
n_qubits int

The number of qubits of the circuit being assembled, which is the number of qubits of the widest block in the list.

required

Returns:

Type Description
IRFragment

The gates of the block, as an IRFragment. Its weight and input indices start at 0, and they are shifted when the blocks are combined into a circuit.

from_dict(d) classmethod

Rebuild a block from the output of to_dict().

Parameters:

Name Type Description Default
d dict

A dictionary returned by to_dict().

required

Returns:

Type Description
'Reuploading'

The rebuilt Reuploading.

required_qubits()

Return in_features: one qubit for each feature.

to_dict()

Return a description of this block that can be saved as JSON.

When a saved model is loaded, the type key selects the block class whose from_dict() rebuilds the block.

Returns:

Type Description
dict

The fields of the block, and its type.

StrongVariational dataclass

depth trainable layers of RZ, RY and RZ rotations and entangling gates.

Each layer applies the rotations RZ, RY and RZ to every qubit, then a controlled-NOT (CNOT) gate from each qubit to the next one. The block is modelled on PennyLane's StronglyEntanglingLayers.

The gates are added one layer at a time: all the RZ rotations, then all the RY rotations, then all the RZ rotations, then the CNOT gates. They are not added as three rotations per qubit. The result is the same, because rotations on different qubits commute. The layered order lets the backends that support it apply each layer of rotations in one fast call, in place of 3 * n_qubits calls on single qubits.

The block takes 3 * depth * n_qubits weights and no inputs.

Parameters:

Name Type Description Default
depth int

The number of layers. It must be positive, and a ValueError is raised otherwise.

required

build(n_qubits)

Build the gates of this block for a circuit with n_qubits qubits.

The layers act on every qubit of the circuit.

Parameters:

Name Type Description Default
n_qubits int

The number of qubits of the circuit being assembled, which is the number of qubits of the widest block in the list.

required

Returns:

Type Description
IRFragment

The gates of the block, as an IRFragment. Its weight and input indices start at 0, and they are shifted when the blocks are combined into a circuit.

from_dict(d) classmethod

Rebuild a block from the output of to_dict().

Parameters:

Name Type Description Default
d dict

A dictionary returned by to_dict().

required

Returns:

Type Description
'StrongVariational'

The rebuilt StrongVariational.

required_qubits()

Return 1, because the block extends to all the qubits of the circuit.

to_dict()

Return a description of this block that can be saved as JSON.

When a saved model is loaded, the type key selects the block class whose from_dict() rebuilds the block.

Returns:

Type Description
dict

The fields of the block, and its type.

Variational dataclass

depth trainable layers of single-qubit rotations and entangling gates.

Each layer applies one trainable rotation to every qubit, then a controlled-NOT (CNOT) gate from each qubit to the next one. The block takes depth * n_qubits weights and no inputs.

Parameters:

Name Type Description Default
depth int

The number of layers. It must be positive, and a ValueError is raised otherwise.

required
rotation GateName

The rotation gate of the trainable layer: "RX", "RY" or "RZ". Default: "RY".

'RY'

build(n_qubits)

Build the gates of this block for a circuit with n_qubits qubits.

The layers act on every qubit of the circuit.

Parameters:

Name Type Description Default
n_qubits int

The number of qubits of the circuit being assembled, which is the number of qubits of the widest block in the list.

required

Returns:

Type Description
IRFragment

The gates of the block, as an IRFragment. Its weight and input indices start at 0, and they are shifted when the blocks are combined into a circuit.

from_dict(d) classmethod

Rebuild a block from the output of to_dict().

Parameters:

Name Type Description Default
d dict

A dictionary returned by to_dict().

required

Returns:

Type Description
'BasicVariational'

The rebuilt BasicVariational.

required_qubits()

Return 1, because the block extends to all the qubits of the circuit.

to_dict()

Return a description of this block that can be saved as JSON.

When a saved model is loaded, the type key selects the block class whose from_dict() rebuilds the block.

Returns:

Type Description
dict

The fields of the block, and its type.