qiboml.models#

Submodules#

qiboml.models.encoding#

class qiboml.models.encoding.QuantumEncoding(nqubits: int, qubits: Optional[tuple[int]] = None, density_matrix: Optional[bool] = False, _circuit: Circuit = None)[source]#

Bases: ABC

Abstract Encoder class.

Parameters:
  • nqubits (int) – total number of qubits.

  • qubits (tuple[int], optional) – set of qubits it acts on, by default range(nqubits).

  • density_matrix (bool, optional) – whether to build the circuit with density_matrix=True, mostly useful for noisy simulations. density_matrix=False by default.

nqubits: int#
qubits: Optional[tuple[int]] = None#
density_matrix: Optional[bool] = False#
_circuit: Circuit = None#
abstract __call__(x: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]]) Circuit[source]#

Abstract call method.

property circuit: Circuit#

Internal initialized circuit.

property differentiable: bool#

Whether the encoder is differentiable. If True the gradient w.r.t. the inputs is calculated, otherwise it is automatically set to zero.

_abc_impl = <_abc._abc_data object>#
class qiboml.models.encoding.PhaseEncoding(nqubits: int, qubits: Optional[tuple[int]] = None, density_matrix: Optional[bool] = False, _circuit: qibo.models.circuit.Circuit = None, encoding_gate: type = <factory>)[source]#

Bases: QuantumEncoding

encoding_gate: type#
__call__(x: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]]) Circuit[source]#

Construct the circuit encoding the x data in the chosen encoding gate.

Parameters:

x (ArrayLike) – the input real data to encode in rotation angles.

Returns:

The constructed circuit.

Return type:

qibo.models.circuit.Circuit

_abc_impl = <_abc._abc_data object>#
_circuit: Circuit = None#
property circuit: Circuit#

Internal initialized circuit.

density_matrix: Optional[bool] = False#
property differentiable: bool#

Whether the encoder is differentiable. If True the gradient w.r.t. the inputs is calculated, otherwise it is automatically set to zero.

qubits: Optional[tuple[int]] = None#
nqubits: int#
class qiboml.models.encoding.BinaryEncoding(nqubits: int, qubits: Optional[tuple[int]] = None, density_matrix: Optional[bool] = False, _circuit: Circuit = None)[source]#

Bases: QuantumEncoding

__call__(x: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]]) Circuit[source]#

Construct the circuit encoding the x binary data in some RX rotation gates with angles either \(\pi\) (for ones) or 0 (for zeros).

Parameters:

x (ArrayLike) – the input binary data.

Returns:

The constructed circuit.

Return type:

qibo.models.circuit.Circuit

property differentiable: bool#

Whether the encoder is differentiable. If True the gradient w.r.t. the inputs is calculated, otherwise it is automatically set to zero.

_abc_impl = <_abc._abc_data object>#
_circuit: Circuit = None#
property circuit: Circuit#

Internal initialized circuit.

density_matrix: Optional[bool] = False#
qubits: Optional[tuple[int]] = None#
nqubits: int#

qiboml.models.ansatze#

qiboml.models.ansatze.hardware_efficient(nqubits: int, qubits: Optional[tuple[int]] = None, nlayers: int = 1, single_block: Optional[Circuit] = None, entangling_block: Optional[Circuit] = None, entangling_gate: str = 'CNOT', architecture: str = 'diagonal', closed_boundary: bool = True, seed: Optional[Union[int, Generator]] = None, backend=None, **kwargs) Circuit[source]#

Create a hardware-efficient ansatz with custom single-qubit layers and entangling blocks.

Parameters:
  • nqubits (int) – Number of qubits \(n\) in the ansatz.

  • qubits (tuple[int], optional) – Qubit indexes to apply the ansatz to. If None, the ansatz is applied to all qubits from \(0\) to \(nqubits-1\). Defaults to None.

  • nlayers (int, optional) – Number of layers (single-qubit + entangling per layer). Defaults to \(1\).

  • single_block (Circuit, optional) – \(1\)-qubit circuit applied to each qubit.

  • None (If) –

:param defaults to a block with qibo.gates.RY and: :param qibo.gates.RZ gates with Haar-random sampled phases. Defaults to None.: :param entangling_block: \(n\)-qubit entangling circuit. Defaults to None. :type entangling_block: Circuit, optional :param entangling_gate: Only used if entangling_block

is None. Two-qubit gate to be used in the entangling layer if entangling_block is not provided. If entangling_gate is a parametrized gate, all phases are initialized as \(0.0\). Defaults to "CNOT".

Parameters:
  • architecture (str, optional) – Only used if entangling_block is None. Architecture of the entangling layer. In alphabetical order, options are: "diagonal", "even_layer", "next_nearest", "odd_layer", "pyramid", "shifted", "v", and "x". The "x" architecture is only defined for an even number of qubits. Defaults to "diagonal".

  • closed_boundary (bool, optional) – Only used if entangling_block is None. If True and architecture not in ["pyramid", "v", "x"], adds a closed-boundary condition to the entangling layer. Defaults to True.

  • seed (int or numpy.random.Generator, optional) – Either a generator of random numbers or a fixed seed to initialize a generator. If None, initializes a generator with a random seed. Default: None.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

  • kwargs (dict, optional) – Additional arguments used to initialize a Circuit object. For details, see the documentation of qibo.models.circuit.Circuit.

Returns:

Constructed hardware-efficient ansatz.

Return type:

qibo.models.circuit.Circuit

qiboml.models.ansatze.HardwareEfficient(nqubits: int, qubits: Optional[tuple[int]] = None, nlayers: int = 1, single_block: Optional[Circuit] = None, entangling_block: Optional[Circuit] = None, entangling_gate: str = 'CNOT', architecture: str = 'diagonal', closed_boundary: bool = True, seed: Optional[Union[int, Generator]] = None, backend=None, **kwargs) Circuit#

Create a hardware-efficient ansatz with custom single-qubit layers and entangling blocks.

Parameters:
  • nqubits (int) – Number of qubits \(n\) in the ansatz.

  • qubits (tuple[int], optional) – Qubit indexes to apply the ansatz to. If None, the ansatz is applied to all qubits from \(0\) to \(nqubits-1\). Defaults to None.

  • nlayers (int, optional) – Number of layers (single-qubit + entangling per layer). Defaults to \(1\).

  • single_block (Circuit, optional) – \(1\)-qubit circuit applied to each qubit.

  • None (If) –

:param defaults to a block with qibo.gates.RY and: :param qibo.gates.RZ gates with Haar-random sampled phases. Defaults to None.: :param entangling_block: \(n\)-qubit entangling circuit. Defaults to None. :type entangling_block: Circuit, optional :param entangling_gate: Only used if entangling_block

is None. Two-qubit gate to be used in the entangling layer if entangling_block is not provided. If entangling_gate is a parametrized gate, all phases are initialized as \(0.0\). Defaults to "CNOT".

Parameters:
  • architecture (str, optional) – Only used if entangling_block is None. Architecture of the entangling layer. In alphabetical order, options are: "diagonal", "even_layer", "next_nearest", "odd_layer", "pyramid", "shifted", "v", and "x". The "x" architecture is only defined for an even number of qubits. Defaults to "diagonal".

  • closed_boundary (bool, optional) – Only used if entangling_block is None. If True and architecture not in ["pyramid", "v", "x"], adds a closed-boundary condition to the entangling layer. Defaults to True.

  • seed (int or numpy.random.Generator, optional) – Either a generator of random numbers or a fixed seed to initialize a generator. If None, initializes a generator with a random seed. Default: None.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

  • kwargs (dict, optional) – Additional arguments used to initialize a Circuit object. For details, see the documentation of qibo.models.circuit.Circuit.

Returns:

Constructed hardware-efficient ansatz.

Return type:

qibo.models.circuit.Circuit

qiboml.models.ansatze.brickwork_givens(nqubits: int, weight: int, full_hwp: bool = False, **kwargs)[source]#

Create a Hamming-weight-preserving circuit based on brickwork layers of two-qubit Givens rotations.

Parameters:
  • nqubits (int) – Total number of qubits.

  • weight (int) – Hamming weight to be encoded.

  • full_hwp (bool, optional) – If False, returns circuit with the necessary qibo.gates.X gates included to generate the initial Hamming weight to be preserved. If True, circuit does not include the qibo.gates.X gates. Defaults to False.

  • kwargs (dict, optional) – Additional arguments used to initialize a Circuit object. For details, see the documentation of qibo.models.circuit.Circuit.

Returns:

Hamming-weight-preserving brickwork circuit.

Return type:

qibo.models.circuit.Circuit

References

1. B. T. Gard, L. Zhu1, G. S. Barron, N. J. Mayhall, S. E. Economou, and Edwin Barnes, Efficient symmetry-preserving state preparation circuits for the variational quantum eigensolver algorithm, npj Quantum Information (2020) 6:10.

qiboml.models.decoding#

class qiboml.models.decoding.QuantumDecoding(nqubits: int, qubits: Optional[Tuple[int]] = None, wire_names: Optional[Union[Tuple[int], Tuple[str]]] = None, nshots: Optional[int] = None, backend: Optional[Backend] = None, transpiler: Optional[Passes] = None, noise_model: Optional[NoiseModel] = None, density_matrix: Optional[bool] = False, _circuit: Circuit = None)[source]#

Bases: object

Abstract decoder class.

Parameters:
  • nqubits (int) – total number of qubits.

  • qubits (Tuple[int], optional) – set of qubits it acts on, by default range(nqubits).

  • wire_names (Tuple[int] or Tuple[str], optional) – names to be given to the wires, this has to have len equal to nqubits. Additionally, this is mostly useful when executing on hardware to select which qubits to make use of. Namely, if the chip has qubits named: ` ("a", "b", "c", "d") ` and we wish to deploy a two qubits circuit on the first and last qubits you have to build it as: ` decoding = QuantumDecoding(nqubits=2, wire_names=("a", "d")) `

  • nshots (int, optional) – number of shots used for circuit execution and sampling.

  • backend (qibo.backends.Backend, optional) – backend used for computation, by default the globally-set backend is used.

  • transpiler (qibo.transpiler.Passes, optional) – transpiler to run before circuit execution, by default no transpilation is performed on the circuit (transpiler=None).

  • noise_model (qibo.noise.NoiseModel, optional) – a NoiseModel of Qibo, which is applied to the given circuit to perform noisy simulations. In case a transpiler is passed, the noise model is applied to the transpiled circuit. Defaults to None, and no noise is added.

  • density_matrix (bool, optional) – if True, density matrix simulation is performed instead of state-vector simulation.

nqubits: int#
qubits: Optional[Tuple[int]] = None#
wire_names: Optional[Union[Tuple[int], Tuple[str]]] = None#
nshots: Optional[int] = None#
backend: Optional[Backend] = None#
transpiler: Optional[Passes] = None#
noise_model: Optional[NoiseModel] = None#
density_matrix: Optional[bool] = False#
_circuit: Circuit = None#
__call__(circuit: Circuit) Union[CircuitResult, QuantumState, MeasurementOutcomes][source]#

Combine the input and internal circuits and execute them with the internal backend.

Parameters:

circuit (qibo.models.circuit.Circuit) – Input circuit.

Returns:

qibo.result.CircuitResult or qibo.result.QuantumState or qibo.result.MeasurementOutcomes: Resulting object storing results of circuit execution.

preprocessing(x: Circuit) Circuit[source]#

Perform some preprocessing on the input circuit to run with the settings specified by the decoder. In detail, transpilation and noise application on the input circuit is performed.

align_circuits(x: Circuit)[source]#

Align some attributes of the input circuit with the internal one, e.g. sets the density_matrix and wire_names.

transpile(x: Circuit) Circuit[source]#

Transpile a given circuit x using the instructions provided by the transpiler attribute.

apply_noise(x: Circuit) Circuit[source]#

Apply the decoder noise_model to the target circuit.

property circuit: Circuit#

A copy of the internal circuit.

Returns:

a copy of the internal circuit.

Return type:

(Circuit)

set_backend(backend: Backend)[source]#

Set the internal backend.

Parameters:

backend (Backend) – backend to be set.

property output_shape#

The shape of the decoded outputs.

property analytic: bool#

Whether the decoder is analytic, i.e. the gradient is ananlytically computable, or not (e.g. if sampling is involved).

Returns:

True if nshots is None, False otherwise.

Return type:

(bool)

_align_density_matrix(x: Circuit)[source]#

Share the density matrix attribute with the input circuit.

_align_wire_names(x: Circuit)[source]#

Share the wire names with the input circuit.

_temporary_nshots(nshots)[source]#

Context manager to execute the decoder with a custom number of shots.

class qiboml.models.decoding.Probabilities(nqubits: int, qubits: Optional[Tuple[int]] = None, wire_names: Optional[Union[Tuple[int], Tuple[str]]] = None, nshots: Optional[int] = None, backend: Optional[Backend] = None, transpiler: Optional[Passes] = None, noise_model: Optional[NoiseModel] = None, density_matrix: Optional[bool] = False, _circuit: Circuit = None)[source]#

Bases: QuantumDecoding

The probabilities decoder.

__call__(x: Circuit) Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]][source]#

Computes the final state probabilities.

Parameters:

x (qibo.models.circuit.Circuit) – Input circuit.

Returns:

the final probabilities.

Return type:

ArrayLike

property output_shape: Tuple[int, int]#

Shape of the output probabilities.

Returns:

A (1, 2**nqubits) shape.

Return type:

Tuple[int, int]

property analytic: bool#

Whether the decoder is analytic, i.e. the gradient is ananlytically computable, or not (e.g. if sampling is involved).

Returns:

True if nshots is None, False otherwise.

Return type:

(bool)

_align_density_matrix(x: Circuit)#

Share the density matrix attribute with the input circuit.

_align_wire_names(x: Circuit)#

Share the wire names with the input circuit.

_circuit: Circuit = None#
_temporary_nshots(nshots)#

Context manager to execute the decoder with a custom number of shots.

align_circuits(x: Circuit)#

Align some attributes of the input circuit with the internal one, e.g. sets the density_matrix and wire_names.

apply_noise(x: Circuit) Circuit#

Apply the decoder noise_model to the target circuit.

backend: Optional[Backend] = None#
property circuit: Circuit#

A copy of the internal circuit.

Returns:

a copy of the internal circuit.

Return type:

(Circuit)

density_matrix: Optional[bool] = False#
noise_model: Optional[NoiseModel] = None#
nshots: Optional[int] = None#
preprocessing(x: Circuit) Circuit#

Perform some preprocessing on the input circuit to run with the settings specified by the decoder. In detail, transpilation and noise application on the input circuit is performed.

qubits: Optional[Tuple[int]] = None#
set_backend(backend: Backend)#

Set the internal backend.

Parameters:

backend (Backend) – backend to be set.

transpile(x: Circuit) Circuit#

Transpile a given circuit x using the instructions provided by the transpiler attribute.

transpiler: Optional[Passes] = None#
wire_names: Optional[Union[Tuple[int], Tuple[str]]] = None#
nqubits: int#
class qiboml.models.decoding.Expectation(nqubits: int, qubits: Optional[Tuple[int]] = None, wire_names: Optional[Union[Tuple[int], Tuple[str]]] = None, nshots: Optional[int] = None, backend: Optional[Backend] = None, transpiler: Optional[Passes] = None, noise_model: Optional[NoiseModel] = None, density_matrix: Optional[bool] = False, _circuit: Circuit = None, observable: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes], Hamiltonian] = None, mitigation_config: Optional[Dict[str, Any]] = None, calibrator: Optional[Calibrator] = None)[source]#

Bases: QuantumDecoding

The expectation value decoder.

Args:
observable (ArrayLike or qibo.hamiltonians.Hamiltonian): The observable

to calculate the expectation value of. Defaults to \(Z_0 + Z_1 + ... + Z_n\).

mitigation_config (dict): configuration of the real-time quantum error mitigation

method in case it is desired. The real-time quantum error mitigation algorithm from Ref. [1] is proposed, and consists in performing a real-time check of the reliability of a learned mitigation map. This is done by constructing a reference error-sensitive Clifford circuit, which preserves the size of the original, target one. When the decoder is called, the reliability of the mitigation map is checked by computing a simple metric :math:`D = |E_{

m noisy} - E_{ m mitigated}|`.

If the metric is found exceeding an arbitrary threshold value \(\delta\), then a chosen data-driven error mitigation technique is executed to retrieve the mitigation map. To successfully check the reliability of the mitigation map or computing the map itself, it is recommended to use a number of shots which leads to a statistical noise (due to measurements) :math:`

arepsilon << delta`.

For this reason, the real-time error mitigation algorithm can be customized by passing also a min_iterations argument, which will define the minimum number of decoding calls which have to happen before the mitigation map check is performed. An example of real-time error mitigation configuration is:

mitigation_config = {
    "threshold": 2e-1,
    "min_iterations": 500,
    "method": "CDR",
    "method_kwargs": {"n_training_samples": 100, "nshots": 10000},
}

The given example is performing real-time error mitigation with the request of computing the mitigation map via Clifford Data Regression whenever the reference expectation value differs from the mitigated one of \(\delta > 0.2\). This check is performed every 500 iterations and, in case it is required, the mitigation map is computed executing circuits with nshots=10000.

References:

1. M. Robbiati, A. Sopena, A. Papaluca, and S. Carrazza, Real-time error mitigation for variational optimization on quantum hardware, arxiv:2311.05680 (2023).

observable: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes], Hamiltonian] = None#
mitigation_config: Optional[Dict[str, Any]] = None#
calibrator: Optional[Calibrator] = None#
__call__(x: Circuit) Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]][source]#

Execute the input circuit and calculate the expectation value of the internal observable on the final state.

Parameters:

x (qibo.models.circuit.Circuit) – input circuit.

Returns:

the calculated expectation value.

Return type:

ArrayLike

property output_shape: Tuple[int, int]#

Shape of the output expectation value.

Returns:

A (1, 1) shape.

Return type:

Tuple[int, int]

set_backend(backend: Backend) None[source]#

Set the internal and observable’s backends.

Parameters:

backend (qibo.backends.Backend) – backend to be set.

_align_density_matrix(x: Circuit)#

Share the density matrix attribute with the input circuit.

_align_wire_names(x: Circuit)#

Share the wire names with the input circuit.

_circuit: Circuit = None#
_temporary_nshots(nshots)#

Context manager to execute the decoder with a custom number of shots.

align_circuits(x: Circuit)#

Align some attributes of the input circuit with the internal one, e.g. sets the density_matrix and wire_names.

property analytic: bool#

Whether the decoder is analytic, i.e. the gradient is ananlytically computable, or not (e.g. if sampling is involved).

Returns:

True if nshots is None, False otherwise.

Return type:

(bool)

apply_noise(x: Circuit) Circuit#

Apply the decoder noise_model to the target circuit.

backend: Optional[Backend] = None#
property circuit: Circuit#

A copy of the internal circuit.

Returns:

a copy of the internal circuit.

Return type:

(Circuit)

density_matrix: Optional[bool] = False#
noise_model: Optional[NoiseModel] = None#
nshots: Optional[int] = None#
preprocessing(x: Circuit) Circuit#

Perform some preprocessing on the input circuit to run with the settings specified by the decoder. In detail, transpilation and noise application on the input circuit is performed.

qubits: Optional[Tuple[int]] = None#
transpile(x: Circuit) Circuit#

Transpile a given circuit x using the instructions provided by the transpiler attribute.

transpiler: Optional[Passes] = None#
wire_names: Optional[Union[Tuple[int], Tuple[str]]] = None#
nqubits: int#
class qiboml.models.decoding.State(nqubits: int, qubits: Optional[Tuple[int]] = None, wire_names: Optional[Union[Tuple[int], Tuple[str]]] = None, nshots: Optional[int] = None, backend: Optional[Backend] = None, transpiler: Optional[Passes] = None, noise_model: Optional[NoiseModel] = None, density_matrix: Optional[bool] = False, _circuit: Circuit = None)[source]#

Bases: QuantumDecoding

The state decoder.

__call__(x: Circuit) Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]][source]#

Compute the final state of the input circuit and separates it in its real and imaginary parts stacked on top of each other.

Parameters:

x (qibo.models.circuit.Circuit) – input Circuit.

Returns:

The final state.

Return type:

ArrayLike

property output_shape: Tuple[int, int, int]#

Shape of the output state.

Returns:

A (2, 1, 2**nqubits) shape.

Return type:

Tuple[int, int, int]

property analytic: bool#

Whether the decoder is analytic, i.e. the gradient is ananlytically computable, or not (e.g. if sampling is involved).

Returns:

True if nshots is None, False otherwise.

Return type:

(bool)

_align_density_matrix(x: Circuit)#

Share the density matrix attribute with the input circuit.

_align_wire_names(x: Circuit)#

Share the wire names with the input circuit.

_circuit: Circuit = None#
_temporary_nshots(nshots)#

Context manager to execute the decoder with a custom number of shots.

align_circuits(x: Circuit)#

Align some attributes of the input circuit with the internal one, e.g. sets the density_matrix and wire_names.

apply_noise(x: Circuit) Circuit#

Apply the decoder noise_model to the target circuit.

backend: Optional[Backend] = None#
property circuit: Circuit#

A copy of the internal circuit.

Returns:

a copy of the internal circuit.

Return type:

(Circuit)

density_matrix: Optional[bool] = False#
noise_model: Optional[NoiseModel] = None#
nshots: Optional[int] = None#
preprocessing(x: Circuit) Circuit#

Perform some preprocessing on the input circuit to run with the settings specified by the decoder. In detail, transpilation and noise application on the input circuit is performed.

qubits: Optional[Tuple[int]] = None#
set_backend(backend: Backend)#

Set the internal backend.

Parameters:

backend (Backend) – backend to be set.

transpile(x: Circuit) Circuit#

Transpile a given circuit x using the instructions provided by the transpiler attribute.

transpiler: Optional[Passes] = None#
wire_names: Optional[Union[Tuple[int], Tuple[str]]] = None#
nqubits: int#
class qiboml.models.decoding.Samples(nqubits: int, qubits: Optional[Tuple[int]] = None, wire_names: Optional[Union[Tuple[int], Tuple[str]]] = None, nshots: Optional[int] = None, backend: Optional[Backend] = None, transpiler: Optional[Passes] = None, noise_model: Optional[NoiseModel] = None, density_matrix: Optional[bool] = False, _circuit: Circuit = None)[source]#

Bases: QuantumDecoding

The samples decoder.

__call__(x: Circuit) Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]][source]#

Sample the final state of the circuit.

Parameters:

x (qibo.models.circuit.Circuit) – input circuit.

Returns:

Generated samples.

Return type:

ArrayLike

property output_shape: Tuple[int, int]#

Shape of the output samples.

Returns:

A (nshots, nqubits) shape.

Return type:

Tuple[int, int]

property analytic: bool#

Whether the decoder is analytic, i.e. the gradient is ananlytically computable, or not (e.g. if sampling is involved).

Returns:

True if nshots is None, False otherwise.

Return type:

(bool)

_align_density_matrix(x: Circuit)#

Share the density matrix attribute with the input circuit.

_align_wire_names(x: Circuit)#

Share the wire names with the input circuit.

_circuit: Circuit = None#
_temporary_nshots(nshots)#

Context manager to execute the decoder with a custom number of shots.

align_circuits(x: Circuit)#

Align some attributes of the input circuit with the internal one, e.g. sets the density_matrix and wire_names.

apply_noise(x: Circuit) Circuit#

Apply the decoder noise_model to the target circuit.

backend: Optional[Backend] = None#
property circuit: Circuit#

A copy of the internal circuit.

Returns:

a copy of the internal circuit.

Return type:

(Circuit)

density_matrix: Optional[bool] = False#
noise_model: Optional[NoiseModel] = None#
nshots: Optional[int] = None#
preprocessing(x: Circuit) Circuit#

Perform some preprocessing on the input circuit to run with the settings specified by the decoder. In detail, transpilation and noise application on the input circuit is performed.

qubits: Optional[Tuple[int]] = None#
set_backend(backend: Backend)#

Set the internal backend.

Parameters:

backend (Backend) – backend to be set.

transpile(x: Circuit) Circuit#

Transpile a given circuit x using the instructions provided by the transpiler attribute.

transpiler: Optional[Passes] = None#
wire_names: Optional[Union[Tuple[int], Tuple[str]]] = None#
nqubits: int#
class qiboml.models.decoding.VariationalQuantumLinearSolver(nqubits: int, qubits: Optional[Tuple[int]] = None, wire_names: Optional[Union[Tuple[int], Tuple[str]]] = None, nshots: Optional[int] = None, backend: Optional[Backend] = None, transpiler: Optional[Passes] = None, noise_model: Optional[NoiseModel] = None, density_matrix: Optional[bool] = False, _circuit: Circuit = None, *, target_state: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]], a_matrix: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]])[source]#

Bases: QuantumDecoding

Decoder for the Variational Quantum Linear Solver (VQLS).

Parameters:
  • target_state (ArrayLike) – Target solution vector \(\ket{b}\).

  • A (ArrayLike) – The matrix A in the linear system \(A \, \ket{x} = \ket{b}\).

Reference:

C. Bravo-Prieto, R. LaRose, M. Cerezo, Y. Subasi, L. Cincio, and P. J. Coles, Variational quantum linear solver, Quantum 7, 1188 (2023).

target_state: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]]#
a_matrix: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]]#
__call__(circuit: Circuit)[source]#

Combine the input and internal circuits and execute them with the internal backend.

Parameters:

circuit (qibo.models.circuit.Circuit) – Input circuit.

Returns:

qibo.result.CircuitResult or qibo.result.QuantumState or qibo.result.MeasurementOutcomes: Resulting object storing results of circuit execution.

property output_shape: Tuple[int, int]#

The shape of the decoded outputs.

property analytic: bool#

Whether the decoder is analytic, i.e. the gradient is ananlytically computable, or not (e.g. if sampling is involved).

Returns:

True if nshots is None, False otherwise.

Return type:

(bool)

_align_density_matrix(x: Circuit)#

Share the density matrix attribute with the input circuit.

_align_wire_names(x: Circuit)#

Share the wire names with the input circuit.

_circuit: Circuit = None#
_temporary_nshots(nshots)#

Context manager to execute the decoder with a custom number of shots.

align_circuits(x: Circuit)#

Align some attributes of the input circuit with the internal one, e.g. sets the density_matrix and wire_names.

apply_noise(x: Circuit) Circuit#

Apply the decoder noise_model to the target circuit.

backend: Optional[Backend] = None#
property circuit: Circuit#

A copy of the internal circuit.

Returns:

a copy of the internal circuit.

Return type:

(Circuit)

density_matrix: Optional[bool] = False#
noise_model: Optional[NoiseModel] = None#
nshots: Optional[int] = None#
preprocessing(x: Circuit) Circuit#

Perform some preprocessing on the input circuit to run with the settings specified by the decoder. In detail, transpilation and noise application on the input circuit is performed.

qubits: Optional[Tuple[int]] = None#
set_backend(backend: Backend)#

Set the internal backend.

Parameters:

backend (Backend) – backend to be set.

transpile(x: Circuit) Circuit#

Transpile a given circuit x using the instructions provided by the transpiler attribute.

transpiler: Optional[Passes] = None#
wire_names: Optional[Union[Tuple[int], Tuple[str]]] = None#
nqubits: int#
qiboml.models.decoding._real_time_mitigation_check(decoder: Expectation, circuit: Circuit)[source]#

Helper function to execute the real time mitigation check and, if necessary, to compute the reference circuit expectation value.

qiboml.models.decoding._check_or_recompute_map(decoder: Expectation, x: Circuit)[source]#

Helper function to recompute the mitigation map.

qiboml.models.optimizers#

class qiboml.models.optimizers.ExactGeodesicTransportCG(nqubits: int, weight: int, loss_fn: Callable[[...], tuple[float, Any]], loss_kwargs: dict | None = None, initial_parameters: Optional[Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]]] = None, backtrack_rate: float = 0.9, backtrack_multiplier: float = 1.5, backtrack_min_lr: float = 1e-06, c1: float = 0.001, c2: float = 0.9, callback: Optional[Callable[[...], None]] = None, seed: int | None = None, backend: Backend = None)[source]#

Bases: object

Exact Geodesic Transport with Conjugate Gradients Optimizer.

Implements the Exact Geodesic Transport with Conjugate Gradients (EGT-CG) optimizer, a curvature-aware Riemannian optimizer designed specifically for variational circuits based on the Hamming-weight encoder (HWE) ansatze. It updates parameters along exact geodesic paths on the hyperspherical manifold defined by the HWE, combining analytic metric computation, conjugate-gradient memory, and dynamic learning rates for fast, globally convergent optimization.

Parameters:
  • nqubits (int) – Number of qubits in the quantum circuit.

  • weight (int) – Hamming weight to encode.

  • loss_fn (str or Callable) – if str, only possibility is exp_val, for expectation value loss (i.e., running VQE). It can also be a Callable to be used as the loss function. First two arguments (mandatory) are circuit and backend for execution.

  • loss_kwargs – (dict, optional): Additional arguments to be passed to the loss function. For VQE (loss_fn = "exp_val"), include item "hamiltonian": hamiltonian, where hamiltonian is passed as ArrayLike, scipy sparse or backend-specific sparse.

  • initial_parameters (ArrayLike, optional) – Initial hyperspherical angles parameterizing the amplitudes. If None, initializes from a Haar-random state.

  • backtrack_rate (float, optional) – Backtracking rate for Wolfe condition line search. Defaults to \(0.9\).

  • backtrack_multiplier (float, optional) – Scaling factor applied to the initial learning rate for the backtrack. Usually, it’s greater than 1 to guarantee a wider search space. Defaults to \(1.5\).

  • backtrack_min_lr (float, optional) – Minimum learning rate to be tested in the backtrack. Defaults to \(10^{-6}\).

  • c1 (float, optional) – Constant for Armijo condition (sufficient decrease) in Wolfe line search. Defaults to \(10^{-3}\).

  • c2 (float, optional) – Constant for curvature condition in Wolfe line search. It should satisfy c1 < c2 < 1. Defaults to \(0.9\).

  • callback (Callable, optinal) – callback function. First two positional arguments are iter_number and loss_value.

  • seed (int, optional) – random seed. Controls initialization.

  • backend (qibo.backends.abstract.Backend, optional) – backend to be used in the execution. If None, it uses the current backend. Defaults to None.

Returns:

Instantiated optimizer object.

Return type:

qiboml.models.optimizers.ExactGeodesicTransportCG

References

A. J. Ferreira-Martins, R. M. S. Farias, G. Camilo, T. O. Maciel, A. Tosta, R. Lin, A. Alhajri, T. Haug, and L. Aolita, Quantum optimization with exact geodesic transport, arXiv:2506.17395 (2025).

get_subspace_hamiltonian() Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]][source]#

Computes the Hamiltonian restricted to the fixed-weight subspace and represented as a dense matrix in the active backend.

Assumes self.hamiltonian is in COO format of the respective backend.

Returns:

Dense matrix representing the hamiltonian in the subspace.

Return type:

ArrayLike

initialize_cg_state()[source]#

Initialize CG state.

Sets up the internal variables x, u, v, and initial step size eta based on the current angles.

angles_to_amplitudes(angles: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]]) Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]][source]#

Convert angles to amplitudes.

Parameters:

angles (ArrayLike) – Angles in hyperspherical coordinates.

Returns:

Amplitudes calculated from the hyperspherical coordinates.

Return type:

ArrayLike

get_jacobian() Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]][source]#

Compute Jacobian of amplitudes wrt angles.

Returns:

Jacobian matrix.

Return type:

ArrayLike

metric_tensor() Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]][source]#

Compute the diagonal metric tensor in hyperspherical coordinates.

Returns:

Diagonal elements of the metric tensor.

Return type:

ArrayLike

tangent_vector() Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]][source]#

Compute the Riemannian gradient (tangent vector) at the current point on the hypersphere.

If loss is expectation value, uses the analytical gradient computation from amplitudes.

If it is a generic loss, performs backpropagation in parameters space, then uses the jacobian to go to amplitudes coordinates.

Returns:

Tangent vector in the tangent space of the hypersphere.

Return type:

ArrayLike

regularization(angles: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]]) Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]][source]#

Applies regularization to vector of parameters after update, effectively changing charts away from singularities. Returns corresponding amplitudes directly.

Parameters:

ArrayLike (angles) – vector of parameters.

Returns:

vector of amplitudes post-regularization.

Return type:

ArrayLike

optimize_step_size(x_prev: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]], u_prev: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]], v_prev: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]], loss_prev: float) Tuple[Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]], Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]], float][source]#

Perform Wolfe line search to determine optimal step size eta via the satisfaction of the Wolfe conditions.

Parameters:
  • x_prev (ArrayLike) – Previous amplitudes on the sphere.

  • u_prev (ArrayLike) – Previous conjugate search direction.

  • v_prev (ArrayLike) – Previous search direction.

  • loss_prev (float) – Loss at previous amplitudes.

Returns:

Respectively: updated amplitudes, new search direction, and optimal step size.

Return type:

Tuple

exponential_map_with_direction(direction: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]], eta: float) Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]][source]#

Applies xponential map from current point along specified direction.

Parameters:
  • direction (ArrayLike) – Tangent vector direction.

  • eta (float) – Step size.

Returns:

Amplitudes of new point on the hypersphere.

Return type:

ArrayLike

amplitudes_to_angles(x: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]]) Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]][source]#

Computes the angles corresponding to a given amplitudes vector.

Parameters:

x (ArrayLike) – Amplitudes vector.

Returns:

Corresponding angles.

Return type:

ArrayLike

parallel_transport(u: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]], v: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]], a: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]], eta=None) Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]][source]#

Parallel transport a tangent vector u along geodesic defined by v.

Parameters:
  • u (ArrayLike) – Vector to transport.

  • v (ArrayLike) – Direction of geodesic.

  • a (ArrayLike) – Starting point on sphere.

  • eta (float, optional) – Step size. If None, defaults to current eta. Defaults to None.

Returns:

Transported vector.

Return type:

ArrayLike

beta_dy(v_next: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]], transported_u: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]], st: float) float[source]#

Compute Dai and Yuan Beta.

Parameters:
  • v_next (ArrayLike) – Next gradient.

  • x_next (ArrayLike) – Next point.

  • transported_u (ArrayLike) – Parallel-transported u.

  • st (float) – Scaling factor.

Returns:

Dai-Yuan beta value.

Return type:

float

beta_hs(v_next: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]], transported_u: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]], transported_v: Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]], lt: float, st: float) float[source]#

Compute Hestenes-Stiefel conjugate gradient beta.

Parameters:
  • v_next (ArrayLike) – Next gradient.

  • x_next (ArrayLike) – Next point.

  • transported_u (ArrayLike) – Parallel-transported u.

  • transported_v (ArrayLike) – Parallel-transported v.

  • lt (float) – Scaling factor.

  • st (float) – Scaling factor.

Returns:

Hestenes-Stiefel beta value.

Return type:

float

run_egt_cg(steps: int = 100, tolerance: float = 1e-08) Tuple[float, Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]], Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]]][source]#

Run the EGT-CG optimizer for a specified number of steps.

Parameters:
  • steps (int, optional) – Number of optimization iterations. Defaults to \(100\).

  • tolerance (float, optional) – Maximum tolerance for the residue of the gradient update. Defaults to \(10^{-8}\).

Returns:

final_loss: Final loss value. losses: Loss at each iteration. final_parameters: Final optimized parameters (angles).

Return type:

Tuple[float, ArrayLike, ArrayLike]

_loss_internal(circuit: Circuit, backend: Backend, **kwargs) float[source]#

Wrapper function for the loss, used to update attribute n_call_loss every time the loss is executed.

Parameters:
  • circuit (qibo.models.circuit.Circuit) – circuit used to compute the loss.

  • backend (qibo.backends.abstract.Backend) – backend for execution.

Returns:

value of loss function.

Return type:

float

_gradient_func_internal() Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]][source]#

Compute the gradient of self.loss w.r.t the trainable parameters stored inside self.circuit, using backpropagation of the backend specified by platform. This is used if loss != exp_val.

Returns:

gradient vector as an array of the backend platform.

Return type:

ArrayLike