Models

Qibo provides models for both the circuit based and the adiabatic quantum computation paradigms. Circuit based models include Circuit models which allow defining arbitrary circuits and Quantum Fourier Transform (QFT) such as the Quantum Fourier Transform (qibo.models.QFT) and the Variational Quantum Eigensolver (qibo.models.VQE). Adiabatic quantum computation is simulated using the Time evolution of state vectors.

The general purpose model is called Circuit and holds the list of gates that are applied to the state vector or density matrix. All Circuit models inherit the qibo.abstractions.circuit.AbstractCircuit which implements basic properties of the circuit, such as the list of gates and the number of qubits.

In order to perform calculations and apply gates to a state vector a backend has to be used. The main Circuit used for simulation is defined in qibo.core.circuit.Circuit. This uses an abstract backend object K to perform calculation which can be one of the backends defined in qibo/backends.

Circuit models

Abstract circuit

class qibo.abstractions.circuit.AbstractCircuit(nqubits)

Circuit object which holds a list of gates.

This circuit is symbolic and cannot perform calculations. A specific backend has to be used for performing calculations. All backend-based circuits should inherit AbstractCircuit.

Qibo provides the following circuits:

All circuits use core as the computation backend.

Parameters

nqubits (int) – Total number of qubits in the circuit.

on_qubits(*q)

Generator of gates contained in the circuit acting on specified qubits.

Useful for adding a circuit as a subroutine in a larger circuit.

Parameters

q (int) – Qubit ids that the gates should act.

Example

from qibo import gates, models
# create small circuit on 4 qubits
smallc = models.Circuit(4)
smallc.add((gates.RX(i, theta=0.1) for i in range(4)))
smallc.add((gates.CNOT(0, 1), gates.CNOT(2, 3)))
# create large circuit on 8 qubits
largec = models.Circuit(8)
largec.add((gates.RY(i, theta=0.1) for i in range(8)))
# add the small circuit to the even qubits of the large one
largec.add(smallc.on_qubits(*range(0, 8, 2)))
copy(deep: bool = False)

Creates a copy of the current circuit as a new Circuit model.

Parameters

deep (bool) – If True copies of the gate objects will be created for the new circuit. If False, the same gate objects of circuit will be used.

Returns

The copied circuit object.

invert()

Creates a new Circuit that is the inverse of the original.

Inversion is obtained by taking the dagger of all gates in reverse order. If the original circuit contains measurement gates, these are included in the inverted circuit.

Returns

The circuit inverse.

decompose(*free: int)

Decomposes circuit’s gates to gates supported by OpenQASM.

Parameters

free – Ids of free (work) qubits to use for gate decomposition.

Returns

Circuit that contains only gates that are supported by OpenQASM and has the same effect as the original circuit.

with_noise(noise_map: Union[Tuple[int, int, int], Dict[int, Tuple[int, int, int]]])

Creates a copy of the circuit with noise gates after each gate.

If the original circuit uses state vectors then noise simulation will be done using sampling and repeated circuit execution. In order to use density matrices the original circuit should be created using the density_matrix flag set to True. For more information we refer to the How to perform noisy simulation? example.

Parameters

noise_map (dict) – Dictionary that maps qubit ids to noise probabilities (px, py, pz). If a tuple of probabilities (px, py, pz) is given instead of a dictionary, then the same probabilities will be used for all qubits.

Returns

Circuit object that contains all the gates of the original circuit and additional noise channels on all qubits after every gate.

Example

from qibo.models import Circuit
from qibo import gates
# use density matrices for noise simulation
c = Circuit(2, density_matrix=True)
c.add([gates.H(0), gates.H(1), gates.CNOT(0, 1)])
noise_map = {0: (0.1, 0.0, 0.2), 1: (0.0, 0.2, 0.1)}
noisy_c = c.with_noise(noise_map)

# ``noisy_c`` will be equivalent to the following circuit
c2 = Circuit(2, density_matrix=True)
c2.add(gates.H(0))
c2.add(gates.PauliNoiseChannel(0, 0.1, 0.0, 0.2))
c2.add(gates.H(1))
c2.add(gates.PauliNoiseChannel(1, 0.0, 0.2, 0.1))
c2.add(gates.CNOT(0, 1))
c2.add(gates.PauliNoiseChannel(0, 0.1, 0.0, 0.2))
c2.add(gates.PauliNoiseChannel(1, 0.0, 0.2, 0.1))
check_measured(gate_qubits: Tuple[int])

Helper method for add.

Checks if the qubits that a gate acts are already measured and raises a NotImplementedError if they are because currently we do not allow measured qubits to be reused.

add(gate)

Add a gate to a given queue.

Parameters

gate (qibo.abstractions.gates.Gate) – the gate object to add. See Gates for a list of available gates. gate can also be an iterable or generator of gates. In this case all gates in the iterable will be added in the circuit.

Returns

If the circuit contains measurement gates with collapse=True a sympy.Symbol that parametrizes the corresponding outcome.

property ngates: int

Total number of gates/operations in the circuit.

property depth: int

Circuit depth if each gate is placed at the earliest possible position.

property gate_types: collections.Counter

collections.Counter with the number of appearances of each gate type.

The QASM names are used as gate identifiers.

gates_of_type(gate: Union[str, type]) List[Tuple[int, qibo.abstractions.abstract_gates.Gate]]

Finds all gate objects of specific type.

Parameters

gate (str, type) – The QASM name of a gate or the corresponding gate class.

Returns

List with all gates that are in the circuit and have the same type with the given gate. The list contains tuples (i, g) where i is the index of the gate g in the circuit’s gate queue.

set_parameters(parameters)

Updates the parameters of the circuit’s parametrized gates.

For more information on how to use this method we refer to the How to use parametrized gates? example.

Parameters

parameters – Container holding the new parameter values. It can have one of the following types: List with length equal to the number of parametrized gates and each of its elements compatible with the corresponding gate. Dictionary with keys that are references to the parametrized gates and values that correspond to the new parameters for each gate. Flat list with length equal to the total number of free parameters in the circuit. A backend supported tensor (for example np.ndarray or tf.Tensor) may also be given instead of a flat list.

Example

from qibo.models import Circuit
from qibo import gates
# create a circuit with all parameters set to 0.
c = Circuit(3, accelerators)
c.add(gates.RX(0, theta=0))
c.add(gates.RY(1, theta=0))
c.add(gates.CZ(1, 2))
c.add(gates.fSim(0, 2, theta=0, phi=0))
c.add(gates.H(2))

# set new values to the circuit's parameters using list
params = [0.123, 0.456, (0.789, 0.321)]
c.set_parameters(params)
# or using dictionary
params = {c.queue[0]: 0.123, c.queue[1]: 0.456
          c.queue[3]: (0.789, 0.321)}
c.set_parameters(params)
# or using flat list (or an equivalent `np.array`/`tf.Tensor`)
params = [0.123, 0.456, 0.789, 0.321]
c.set_parameters(params)
get_parameters(format: str = 'list', include_not_trainable: bool = False) Union[List, Dict]

Returns the parameters of all parametrized gates in the circuit.

Inverse method of qibo.abstractions.circuit.AbstractCircuit.set_parameters().

Parameters
  • format (str) – How to return the variational parameters. Available formats are 'list', 'dict' and 'flatlist'. See qibo.abstractions.circuit.AbstractCircuit.set_parameters() for more details on each format. Default is 'list'.

  • include_not_trainable (bool) – If True it includes the parameters of non-trainable parametrized gates in the returned list or dictionary. Default is False.

summary() str

Generates a summary of the circuit.

The summary contains the circuit depths, total number of qubits and the all gates sorted in decreasing number of appearance.

Example

from qibo.models import Circuit
from qibo import gates
c = Circuit(3)
c.add(gates.H(0))
c.add(gates.H(1))
c.add(gates.CNOT(0, 2))
c.add(gates.CNOT(1, 2))
c.add(gates.H(2))
c.add(gates.TOFFOLI(0, 1, 2))
print(c.summary())
# Prints
'''
Circuit depth = 5
Total number of gates = 7
Number of qubits = 3
Most common gates:
h: 3
cx: 2
ccx: 1
'''
abstract property final_state

Returns the final state after full simulation of the circuit.

If the circuit is executed more than once, only the last final state is returned.

abstract execute(initial_state=None, nshots=None)

Executes the circuit. Exact implementation depends on the backend.

See qibo.core.circuit.Circuit.execute() for more details.

to_qasm()

Convert circuit to QASM.

Parameters

filename (str) – The filename where the code is saved.

classmethod from_qasm(qasm_code: str, **kwargs)

Constructs a circuit from QASM code.

Parameters

qasm_code (str) – String with the QASM script.

Returns

A qibo.abstractions.circuit.AbstractCircuit that contains the gates specified by the given QASM script.

Example

from qibo import models, gates

qasm_code = '''OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
h q[0];
h q[1];
cx q[0],q[1];'''
c = models.Circuit.from_qasm(qasm_code)

# is equivalent to creating the following circuit
c2 = models.Circuit(2)
c2.add(gates.H(0))
c2.add(gates.H(1))
c2.add(gates.CNOT(0, 1))
draw(line_wrap=70) str

Draw text circuit using unicode symbols.

Parameters

line_wrap (int) – maximum number of characters per line. This option split the circuit text diagram in chunks of line_wrap characters.

Returns

String containing text circuit diagram.

Circuit

class qibo.core.circuit.Circuit(nqubits)

Backend implementation of qibo.abstractions.circuit.AbstractCircuit.

Performs simulation using state vectors.

Example

from qibo import models, gates
c = models.Circuit(3) # initialized circuit with 3 qubits
c.add(gates.H(0)) # added Hadamard gate on qubit 0
Parameters

nqubits (int) – Total number of qubits in the circuit.

fuse()

Creates an equivalent circuit with the gates fused up to two-qubits.

Returns

A qibo.core.circuit.Circuit object containing qibo.abstractions.gates.FusedGate gates, each of which corresponds to a group of some original gates. For more details on the fusion algorithm we refer to the Circuit fusion section.

Example

from qibo import models, gates
c = models.Circuit(2)
c.add([gates.H(0), gates.H(1)])
c.add(gates.CNOT(0, 1))
c.add([gates.Y(0), gates.Y(1)])
# create circuit with fused gates
fused_c = c.fuse()
# now ``fused_c`` contains a single ``FusedGate`` that is
# equivalent to applying the five original gates
compile()

Compiles the circuit as a Tensorflow graph.

execute(initial_state=None, nshots=None)

Propagates the state through the circuit applying the corresponding gates.

If channels are found within the circuits gates then Qibo will perform the simulation by repeating the circuit execution nshots times. If the circuit contains measurements the corresponding noisy measurement result will be returned, otherwise the final state vectors will be collected to a (nshots, 2 ** nqubits) tensor and returned. The latter usage is memory intensive and not recommended. If the circuit is created with the density_matrix = True flag and contains channels, then density matrices will be used instead of repeated execution. Note that some channels (qibo.abstractions.gates.KrausChannel) can only be simulated using density matrices and not repeated execution. For more details on noise simulation with and without density matrices we refer to How to perform noisy simulation?

Parameters
  • initial_state (array) – Initial state vector as a numpy array of shape (2 ** nqubits,). A Tensorflow tensor with shape nqubits * (2,) is also allowed allowed as an initial state but must have the dtype of the circuit. If initial_state is None the |000...0> state will be used.

  • nshots (int) – Number of shots to sample if the circuit contains measurement gates. If nshots is None the measurement gates will be ignored.

Returns

A qibo.abstractions.states.AbstractState object which holds the final state vector as a tensor of shape (2 ** nqubits,) or the final density matrix as a tensor of shpae (2 ** nqubits, 2 ** nqubits). If nshots is given and the circuit contains measurements the returned circuit object also contains the measured bitstrings.

property final_state

Final state as a tensor of shape (2 ** nqubits,).

The circuit has to be executed at least once before accessing this property, otherwise a ValueError is raised. If the circuit is executed more than once, only the last final state is returned.

Circuit addition

qibo.abstractions.circuit.AbstractCircuit objects support addition. For example

from qibo import models
from qibo import gates

c1 = models.QFT(4)

c2 = models.Circuit(4)
c2.add(gates.RZ(0, 0.1234))
c2.add(gates.RZ(1, 0.1234))
c2.add(gates.RZ(2, 0.1234))
c2.add(gates.RZ(3, 0.1234))

c = c1 + c2

will create a circuit that performs the Quantum Fourier Transform on four qubits followed by Rotation-Z gates.

Circuit fusion

The gates contained in a circuit can be fused up to two-qubits using the qibo.core.circuit.Circuit.fuse() method. This returns a new circuit for which the total number of gates is less than the gates in the original circuit as groups of gates have been fused to a single qibo.abstractions.gates.FusedGate gate. Simulating the new circuit is equivalent to simulating the original one but in most cases more efficient since less gates need to be applied to the state vector.

All one-qubit gates acting on the same qubit in a row are fused together. Once a two-qubit gate acting on a specific pair (q0, q1) is found then it is fused together with the existing fused one-qubit gates on q0 and q1. If a new two-qubit gate is found which acts on either q0 or q1 but not both then the fusion round for the pair (q0, q1) stops and a new fusion round starts for the target qubits of the new two-qubit gate.

For example the following:

from qibo import models, gates

c = models.Circuit(2)
c.add([gates.H(0), gates.H(1)])
c.add(gates.CZ(0, 1))
c.add([gates.X(0), gates.Y(1)])
fused_c = c.fuse()

will create a new circuit with a single qibo.abstractions.gates.FusedGate acting on (0, 1), while the following:

from qibo import models, gates

c = models.Circuit(3)
c.add([gates.H(0), gates.H(1), gates.H(2)])
c.add(gates.CZ(0, 1))
c.add([gates.X(0), gates.Y(1), gates.Z(2)])
c.add(gates.CNOT(1, 2))
c.add([gates.H(0), gates.H(1), gates.H(2)])
fused_c = c.fuse()

will give a circuit with two fused gates, the first of which will act on (0, 1) corresponding to

[H(0), H(1), CZ(0, 1), X(0), H(0)]

and the second will act to (1, 2) corresponding to

[Y(1), Z(2), CNOT(1, 2), H(1), H(2)]

Currently the maximum number of qubits in a fused gate is two. If a gate acting on more qubits is found it is applied as it is without participating in the fusion and new fusion groups are created for the gates that follow and act on its target qubits.

The fusion algorithm fuses gates in the original order given by user. There are no additional simplifications performed such as commuting gates acting on the same qubit or canceling gates even when such simplifications are mathematically possible.

Density matrix circuit

class qibo.core.circuit.DensityMatrixCircuit(nqubits)

Backend implementation of qibo.abstractions.circuit.AbstractCircuit.

Performs simulation using density matrices. Can be initialized using the density_matrix=True flag and supports the use of channels. For more information on the use of density matrices we refer to the Using density matrices? example.

Example

from qibo import models, gates
c = models.Circuit(2, density_matrix=True)
c.add(gates.H(0))
c.add(gates.PauliNoiseChannel(1, px=0.2))
Parameters

nqubits (int) – Total number of qubits in the circuit.

Distributed circuit

class qibo.core.distcircuit.DistributedCircuit(nqubits: int, accelerators: Dict[str, int])

Distributed implementation of qibo.abstractions.circuit.AbstractCircuit in Tensorflow.

Uses multiple accelerator devices (GPUs) for applying gates to the state vector. The full state vector is saved in the given memory device (usually the CPU) during the simulation. A gate is applied by splitting the state to pieces and copying each piece to an accelerator device that is used to perform the matrix multiplication. An accelerator device can be used more than once resulting to logical devices that are more than the physical accelerators in the system.

Distributed circuits currently do not support native tensorflow gates, compilation and callbacks.

Example

from qibo.models import Circuit
# The system has two GPUs and we would like to use each GPU twice
# resulting to four total logical accelerators
accelerators = {'/GPU:0': 2, '/GPU:1': 2}
# Define a circuit on 32 qubits to be run in the above GPUs keeping
# the full state vector in the CPU memory.
c = Circuit(32, accelerators)
Parameters
  • nqubits (int) – Total number of qubits in the circuit.

  • accelerators (dict) – Dictionary that maps device names to the number of times each device will be used. The total number of logical devices must be a power of 2.

on_qubits(*q)

Generator of gates contained in the circuit acting on specified qubits.

Useful for adding a circuit as a subroutine in a larger circuit.

Parameters

q (int) – Qubit ids that the gates should act.

Example

from qibo import gates, models
# create small circuit on 4 qubits
smallc = models.Circuit(4)
smallc.add((gates.RX(i, theta=0.1) for i in range(4)))
smallc.add((gates.CNOT(0, 1), gates.CNOT(2, 3)))
# create large circuit on 8 qubits
largec = models.Circuit(8)
largec.add((gates.RY(i, theta=0.1) for i in range(8)))
# add the small circuit to the even qubits of the large one
largec.add(smallc.on_qubits(*range(0, 8, 2)))
copy(deep: bool = True)

Creates a copy of the current circuit as a new Circuit model.

Parameters

deep (bool) – If True copies of the gate objects will be created for the new circuit. If False, the same gate objects of circuit will be used.

Returns

The copied circuit object.

fuse()

Creates an equivalent circuit with the gates fused up to two-qubits.

Returns

A qibo.core.circuit.Circuit object containing qibo.abstractions.gates.FusedGate gates, each of which corresponds to a group of some original gates. For more details on the fusion algorithm we refer to the Circuit fusion section.

Example

from qibo import models, gates
c = models.Circuit(2)
c.add([gates.H(0), gates.H(1)])
c.add(gates.CNOT(0, 1))
c.add([gates.Y(0), gates.Y(1)])
# create circuit with fused gates
fused_c = c.fuse()
# now ``fused_c`` contains a single ``FusedGate`` that is
# equivalent to applying the five original gates
with_noise(noise_map, measurement_noise=None)

Creates a copy of the circuit with noise gates after each gate.

If the original circuit uses state vectors then noise simulation will be done using sampling and repeated circuit execution. In order to use density matrices the original circuit should be created using the density_matrix flag set to True. For more information we refer to the How to perform noisy simulation? example.

Parameters

noise_map (dict) – Dictionary that maps qubit ids to noise probabilities (px, py, pz). If a tuple of probabilities (px, py, pz) is given instead of a dictionary, then the same probabilities will be used for all qubits.

Returns

Circuit object that contains all the gates of the original circuit and additional noise channels on all qubits after every gate.

Example

from qibo.models import Circuit
from qibo import gates
# use density matrices for noise simulation
c = Circuit(2, density_matrix=True)
c.add([gates.H(0), gates.H(1), gates.CNOT(0, 1)])
noise_map = {0: (0.1, 0.0, 0.2), 1: (0.0, 0.2, 0.1)}
noisy_c = c.with_noise(noise_map)

# ``noisy_c`` will be equivalent to the following circuit
c2 = Circuit(2, density_matrix=True)
c2.add(gates.H(0))
c2.add(gates.PauliNoiseChannel(0, 0.1, 0.0, 0.2))
c2.add(gates.H(1))
c2.add(gates.PauliNoiseChannel(1, 0.0, 0.2, 0.1))
c2.add(gates.CNOT(0, 1))
c2.add(gates.PauliNoiseChannel(0, 0.1, 0.0, 0.2))
c2.add(gates.PauliNoiseChannel(1, 0.0, 0.2, 0.1))
execute(initial_state=None, nshots=None)

Equivalent to qibo.core.circuit.Circuit.execute().

Returns

A qibo.core.states.DistributedState object corresponding to the final state of execution. Note that this state contains the full state vector scattered to pieces and does not create a single tensor unless the user explicitly calls the tensor property. This avoids creating multiple copies of large states in CPU memory.

Quantum Fourier Transform (QFT)

class qibo.models.circuit.QFT(nqubits: int, with_swaps: bool = True, accelerators: Optional[Dict[str, int]] = None)

Creates a circuit that implements the Quantum Fourier Transform.

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

  • with_swaps (bool) – Use SWAP gates at the end of the circuit so that the qubit order in the final state is the same as the initial state.

  • accelerators (dict) – Accelerator device dictionary in order to use a distributed circuit If None a simple (non-distributed) circuit will be used.

Returns

A qibo.models.Circuit that implements the Quantum Fourier Transform.

Example

import numpy as np
from qibo.models import QFT
nqubits = 6
c = QFT(nqubits)
# Random normalized initial state vector
init_state = np.random.random(2 ** nqubits) + 1j * np.random.random(2 ** nqubits)
init_state = init_state / np.sqrt((np.abs(init_state)**2).sum())
# Execute the circuit
final_state = c(init_state)

Variational Quantum Eigensolver (VQE)

class qibo.models.variational.VQE(circuit, hamiltonian)

This class implements the variational quantum eigensolver algorithm.

Parameters

Example

import numpy as np
from qibo import gates, models, hamiltonians
# create circuit ansatz for two qubits
circuit = models.Circuit(2)
circuit.add(gates.RY(0, theta=0))
# create XXZ Hamiltonian for two qubits
hamiltonian = hamiltonians.XXZ(2)
# create VQE model for the circuit and Hamiltonian
vqe = models.VQE(circuit, hamiltonian)
# optimize using random initial variational parameters
initial_parameters = np.random.uniform(0, 2, 1)
vqe.minimize(initial_parameters)
minimize(initial_state, method='Powell', jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None, compile=False, processes=None)

Search for parameters which minimizes the hamiltonian expectation.

Parameters
  • initial_state (array) – a initial guess for the parameters of the variational circuit.

  • method (str) – the desired minimization method. See qibo.optimizers.optimize() for available optimization methods.

  • jac (dict) – Method for computing the gradient vector for scipy optimizers.

  • hess (dict) – Method for computing the hessian matrix for scipy optimizers.

  • hessp (callable) – Hessian of objective function times an arbitrary vector for scipy optimizers.

  • bounds (sequence or Bounds) – Bounds on variables for scipy optimizers.

  • constraints (dict) – Constraints definition for scipy optimizers.

  • tol (float) – Tolerance of termination for scipy optimizers.

  • callback (callable) – Called after each iteration for scipy optimizers.

  • options (dict) – a dictionary with options for the different optimizers.

  • compile (bool) – whether the TensorFlow graph should be compiled.

  • processes (int) – number of processes when using the paralle BFGS method.

Returns

The final expectation value. The corresponding best parameters. The optimization result object. For scipy methods it returns the OptimizeResult, for 'cma' the CMAEvolutionStrategy.result, and for 'sgd' the options used during the optimization.

Quantum Approximate Optimization Algorithm (QAOA)

class qibo.models.variational.QAOA(hamiltonian, mixer=None, solver='exp', callbacks=[], accelerators=None)

Quantum Approximate Optimization Algorithm (QAOA) model.

The QAOA is introduced in arXiv:1411.4028.

Parameters

Example

import numpy as np
from qibo import models, hamiltonians
# create XXZ Hamiltonian for four qubits
hamiltonian = hamiltonians.XXZ(4)
# create QAOA model for this Hamiltonian
qaoa = models.QAOA(hamiltonian)
# optimize using random initial variational parameters
# and default options and initial state
initial_parameters = 0.01 * np.random.random(4)
best_energy, final_parameters, extra = qaoa.minimize(initial_parameters, method="BFGS")
set_parameters(p)

Sets the variational parameters.

Parameters

p (np.ndarray) – 1D-array holding the new values for the variational parameters. Length should be an even number.

execute(initial_state=None)

Applies the QAOA exponential operators to a state.

Parameters

initial_state (np.ndarray) – Initial state vector.

Returns

State vector after applying the QAOA exponential gates.

minimize(initial_p, initial_state=None, method='Powell', jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None, compile=False, processes=None)

Optimizes the variational parameters of the QAOA.

Parameters
  • initial_p (np.ndarray) – initial guess for the parameters.

  • initial_state (np.ndarray) – initial state vector of the QAOA.

  • method (str) – the desired minimization method. See qibo.optimizers.optimize() for available optimization methods.

  • jac (dict) – Method for computing the gradient vector for scipy optimizers.

  • hess (dict) – Method for computing the hessian matrix for scipy optimizers.

  • hessp (callable) – Hessian of objective function times an arbitrary vector for scipy optimizers.

  • bounds (sequence or Bounds) – Bounds on variables for scipy optimizers.

  • constraints (dict) – Constraints definition for scipy optimizers.

  • tol (float) – Tolerance of termination for scipy optimizers.

  • callback (callable) – Called after each iteration for scipy optimizers.

  • options (dict) – a dictionary with options for the different optimizers.

  • compile (bool) – whether the TensorFlow graph should be compiled.

  • processes (int) – number of processes when using the paralle BFGS method.

Returns

The final energy (expectation value of the hamiltonian). The corresponding best parameters. The optimization result object. For scipy methods it returns the OptimizeResult, for 'cma' the CMAEvolutionStrategy.result, and for 'sgd' the options used during the optimization.

Feedback-based Algorithm for Quantum Optimization (FALQON)

class qibo.models.variational.FALQON(hamiltonian, mixer=None, solver='exp', callbacks=[], accelerators=None)

Feedback-based ALgorithm for Quantum OptimizatioN (FALQON) model.

The FALQON is introduced in arXiv:2103.08619. It inherits the QAOA class.

Parameters
  • hamiltonian (qibo.abstractions.hamiltonians.Hamiltonian) – problem Hamiltonian whose ground state is sought.

  • mixer (qibo.abstractions.hamiltonians.Hamiltonian) – mixer Hamiltonian. If None, qibo.hamiltonians.X is used.

  • solver (str) – solver used to apply the exponential operators. Default solver is ‘exp’ (qibo.solvers.Exponential).

  • callbacks (list) – List of callbacks to calculate during evolution.

  • accelerators (dict) – Dictionary of devices to use for distributed execution. See qibo.tensorflow.distcircuit.DistributedCircuit for more details. This option is available only when hamiltonian is a qibo.abstractions.hamiltonians.SymbolicHamiltonian.

Example

import numpy as np
from qibo import models, hamiltonians
# create XXZ Hamiltonian for four qubits
hamiltonian = hamiltonians.XXZ(4)
# create FALQON model for this Hamiltonian
falqon = models.FALQON(hamiltonian)
# optimize using random initial variational parameters
# and default options and initial state
delta_t = 0.01
max_layers = 3
best_energy, final_parameters, extra = falqon.minimize(delta_t, max_layers)
minimize(delta_t, max_layers, initial_state=None, tol=None, callback=None)

Optimizes the variational parameters of the FALQON.

Parameters
  • delta_t (float) – initial guess for the time step. A too large delta_t will make the algorithm fail.

  • max_layers (int) – maximum number of layers allowed for the FALQON.

  • initial_state (np.ndarray) – initial state vector of the FALQON.

  • tol (float) – Tolerance of energy change. If not specified, no check is done.

  • callback (callable) – Called after each iteration for scipy optimizers.

  • options (dict) – a dictionary with options for the different optimizers.

Returns

The final energy (expectation value of the hamiltonian). The corresponding best parameters. extra: variable with historical data for the energy and callbacks.

Grover’s Algorithm

class qibo.models.grover.Grover(oracle, superposition_circuit=None, initial_state_circuit=None, superposition_qubits=None, superposition_size=None, number_solutions=None, target_amplitude=None, check=None, check_args=(), iterative=False)

Model that performs Grover’s algorithm.

For Grover’s original search algorithm: arXiv:quant-ph/9605043 For the iterative version with unknown solutions:arXiv:quant-ph/9605034 For the Grover algorithm with any superposition:arXiv:quant-ph/9712011

Parameters
  • oracle (qibo.core.circuit.Circuit) – quantum circuit that flips the sign using a Grover ancilla initialized with -X-H-. Grover ancilla expected to be last qubit of oracle circuit.

  • superposition_circuit (qibo.core.circuit.Circuit) – quantum circuit that takes an initial state to a superposition. Expected to use the first set of qubits to store the relevant superposition.

  • initial_state_circuit (qibo.core.circuit.Circuit) – quantum circuit that initializes the state. If empty defaults to |000..00>

  • superposition_qubits (int) – number of qubits that store the relevant superposition. Leave empty if superposition does not use ancillas.

  • superposition_size (int) – how many states are in a superposition. Leave empty if its an equal superposition of quantum states.

  • number_solutions (int) – number of expected solutions. Needed for normal Grover. Leave empty for iterative version.

  • target_amplitude (float) – absolute value of the amplitude of the target state. Only for advanced use and known systems.

  • check (function) – function that returns True if the solution has been found. Required of iterative approach. First argument should be the bitstring to check.

  • check_args (tuple) – arguments needed for the check function. The found bitstring not included.

  • iterative (bool) – force the use of the iterative Grover

Example

import numpy as np
from qibo import gates
from qibo.models import Circuit
from qibo.models.grover import Grover
# Create an oracle. Ex: Oracle that detects state |11111>
oracle = Circuit(5 + 1)
oracle.add(gates.X(5).controlled_by(*range(5)))
# Create superoposition circuit. Ex: Full superposition over 5 qubits.
superposition = Circuit(5)
superposition.add([gates.H(i) for i in range(5)])
# Generate and execute Grover class
grover = Grover(oracle, superposition_circuit=superposition, number_solutions=1)
solution, iterations = grover()
initialize()

Initialize the Grover algorithm with the superposition and Grover ancilla.

diffusion()

Construct the diffusion operator out of the superposition circuit.

step()

Combine oracle and diffusion for a Grover step.

circuit(iterations)

Creates circuit that performs Grover’s algorithm with a set amount of iterations.

Parameters

iterations (int) – number of times to repeat the Grover step.

Returns

qibo.core.circuit.Circuit that performs Grover’s algorithm.

iterative_grover(lamda_value=1.2)

Iterative approach of Grover for when the number of solutions is not known.

Parameters

lamda_value (real) – parameter that controls the evolution of the iterative method. Must be between 1 and 4/3.

Returns

bitstring measured and checked as a valid solution. total_iterations (int): number of times the oracle has been called.

Return type

measured (str)

execute(nshots=100, freq=False, logs=False)

Execute Grover’s algorithm.

If the number of solutions is given, calculates iterations, otherwise it uses an iterative approach.

Parameters
  • nshots (int) – number of shots in order to get the frequencies.

  • freq (bool) – print the full frequencies after the exact Grover algorithm.

Returns

bitstring (or list of bitstrings) measured as solution of the search. iterations (int): number of oracle calls done to reach a solution.

Return type

solution (str)

Time evolution

State evolution

class qibo.models.evolution.StateEvolution(hamiltonian, dt, solver='exp', callbacks=[], accelerators=None)

Unitary time evolution of a state vector under a Hamiltonian.

Parameters
  • hamiltonian (qibo.abstractions.hamiltonians.Hamiltonian) – Hamiltonian to evolve under.

  • dt (float) – Time step to use for the numerical integration of Schrondiger’s equation.

  • solver (str) – Solver to use for integrating Schrodinger’s equation. Available solvers are ‘exp’ which uses the exact unitary evolution operator and ‘rk4’ or ‘rk45’ which use Runge-Kutta methods to integrate the Schordinger’s time-dependent equation in time. When the ‘exp’ solver is used to evolve a qibo.core.hamiltonians.SymbolicHamiltonian then the Trotter decomposition of the evolution operator will be calculated and used automatically. If the ‘exp’ is used on a dense qibo.core.hamiltonians.Hamiltonian the full Hamiltonian matrix will be exponentiated to obtain the exact evolution operator. Runge-Kutta solvers use simple matrix multiplications of the Hamiltonian to the state and no exponentiation is involved.

  • callbacks (list) – List of callbacks to calculate during evolution.

  • accelerators (dict) – Dictionary of devices to use for distributed execution. See qibo.core.distcircuit.DistributedCircuit for more details. This option is available only when the Trotter decomposition is used for the time evolution.

Example

import numpy as np
from qibo import models, hamiltonians
# create critical (h=1.0) TFIM Hamiltonian for three qubits
hamiltonian = hamiltonians.TFIM(3, h=1.0)
# initialize evolution model with step dt=1e-2
evolve = models.StateEvolution(hamiltonian, dt=1e-2)
# initialize state to |+++>
initial_state = np.ones(8) / np.sqrt(8)
# execute evolution for total time T=2
final_state2 = evolve(final_time=2, initial_state=initial_state)
execute(final_time, start_time=0.0, initial_state=None)

Runs unitary evolution for a given total time.

Parameters
  • final_time (float) – Final time of evolution.

  • start_time (float) – Initial time of evolution. Defaults to t=0.

  • initial_state (np.ndarray) – Initial state of the evolution.

Returns

Final state vector a tf.Tensor or a qibo.core.distutils.DistributedState when a distributed execution is used.

Adiabatic evolution

class qibo.models.evolution.AdiabaticEvolution(h0, h1, s, dt, solver='exp', callbacks=[], accelerators=None)

Adiabatic evolution of a state vector under the following Hamiltonian:

\[H(t) = (1 - s(t)) H_0 + s(t) H_1\]
Parameters
  • h0 (qibo.abstractions.hamiltonians.Hamiltonian) – Easy Hamiltonian.

  • h1 (qibo.abstractions.hamiltonians.Hamiltonian) – Problem Hamiltonian. These Hamiltonians should be time-independent.

  • s (callable) – Function of time that defines the scheduling of the adiabatic evolution. Can be either a function of time s(t) or a function with two arguments s(t, p) where p corresponds to a vector of parameters to be optimized.

  • dt (float) – Time step to use for the numerical integration of Schrondiger’s equation.

  • solver (str) – Solver to use for integrating Schrodinger’s equation. Available solvers are ‘exp’ which uses the exact unitary evolution operator and ‘rk4’ or ‘rk45’ which use Runge-Kutta methods to integrate the Schordinger’s time-dependent equation in time. When the ‘exp’ solver is used to evolve a qibo.core.hamiltonians.SymbolicHamiltonian then the Trotter decomposition of the evolution operator will be calculated and used automatically. If the ‘exp’ is used on a dense qibo.core.hamiltonians.Hamiltonian the full Hamiltonian matrix will be exponentiated to obtain the exact evolution operator. Runge-Kutta solvers use simple matrix multiplications of the Hamiltonian to the state and no exponentiation is involved.

  • callbacks (list) – List of callbacks to calculate during evolution.

  • accelerators (dict) – Dictionary of devices to use for distributed execution. See qibo.core.distcircuit.DistributedCircuit for more details. This option is available only when the Trotter decomposition is used for the time evolution.

property schedule

Returns scheduling as a function of time.

set_parameters(params)

Sets the variational parameters of the scheduling function.

get_initial_state(state=None)

Casts initial state as a tensor.

If initial state is not given the ground state of h0 is used, which is the common practice in adiabatic evolution.

minimize(initial_parameters, method='BFGS', options=None, messages=False)

Optimize the free parameters of the scheduling function.

Parameters
  • initial_parameters (np.ndarray) – Initial guess for the variational parameters that are optimized. The last element of the given array should correspond to the guess for the total evolution time T.

  • method (str) – The desired minimization method. One of "cma" (genetic optimizer), "sgd" (gradient descent) or any of the methods supported by scipy.optimize.minimize.

  • options (dict) – a dictionary with options for the different optimizers.

  • messages (bool) – If True the loss evolution is shown during optimization.


Gates

All supported gates can be accessed from the qibo.gates module and inherit the base gate object qibo.abstractions.gates.Gate. Read below for a complete list of supported gates.

All gates support the controlled_by method that allows to control the gate on an arbitrary number of qubits. For example

  • gates.X(0).controlled_by(1, 2) is equivalent to gates.TOFFOLI(1, 2, 0),

  • gates.RY(0, np.pi).controlled_by(1, 2, 3) applies the Y-rotation to qubit 0 when qubits 1, 2 and 3 are in the |111> state.

  • gates.SWAP(0, 1).controlled_by(3, 4) swaps qubits 0 and 1 when qubits 3 and 4 are in the |11> state.

Gate models

Abstract gates

class qibo.abstractions.gates.Gate

The base class for gate implementation.

All base gates should inherit this class.

property qubits: Tuple[int]

Tuple with ids of all qubits (control and target) that the gate acts.

property target_qubits: Tuple[int]

Tuple with ids of target qubits.

property control_qubits: Tuple[int]

Tuple with ids of control qubits sorted in increasing order.

property nstates: int

Size of the state vectors that this gate acts on.

property nqubits: int

Number of qubits that this gate acts on.

property density_matrix: bool

Controls if the gate acts on state vectors or density matrices.

commutes(gate: qibo.abstractions.abstract_gates.Gate) bool

Checks if two gates commute.

Parameters

gate – Gate to check if it commutes with the current gate.

Returns

True if the gates commute, otherwise False.

dagger() qibo.abstractions.abstract_gates.Gate

Returns the dagger (conjugate transpose) of the gate.

Returns

A qibo.abstractions.gates.Gate object representing the dagger of the original gate.

decompose(*free) List[qibo.abstractions.abstract_gates.Gate]

Decomposes multi-control gates to gates supported by OpenQASM.

Decompositions are based on arXiv:9503016.

Parameters

free – Ids of free qubits to use for the gate decomposition.

Returns

List with gates that have the same effect as applying the original gate.

Abstract backend gates

class qibo.abstractions.abstract_gates.BaseBackendGate

Abstract class for gate objects that can be used in calculations.

property matrix

Unitary matrix representing the gate in the computational basis.

Single qubit gates

Hadamard (H)

class qibo.abstractions.gates.H(q)

The Hadamard gate.

Parameters

q (int) – the qubit id number.

Pauli X (X)

class qibo.abstractions.gates.X(q)

The Pauli X gate.

Parameters

q (int) – the qubit id number.

decompose(*free: int, use_toffolis: bool = True) List[qibo.abstractions.abstract_gates.Gate]

Decomposes multi-control X gate to one-qubit, CNOT and TOFFOLI gates.

Parameters
  • free – Ids of free qubits to use for the gate decomposition.

  • use_toffolis – If True the decomposition contains only TOFFOLI gates. If False a congruent representation is used for TOFFOLI gates. See qibo.abstractions.gates.TOFFOLI for more details on this representation.

Returns

List with one-qubit, CNOT and TOFFOLI gates that have the same effect as applying the original multi-control gate.

Pauli Y (Y)

class qibo.abstractions.gates.Y(q)

The Pauli Y gate.

Parameters

q (int) – the qubit id number.

Pauli Z (Z)

class qibo.abstractions.gates.Z(q)

The Pauli Z gate.

Parameters

q (int) – the qubit id number.

Identity (I)

class qibo.abstractions.gates.I(*q)

The identity gate.

Parameters

*q (int) – the qubit id numbers.

Measurement (M)

class qibo.abstractions.gates.M(*q, register_name: Optional[str] = None, collapse: bool = False, p0: Optional[ProbsType] = None, p1: Optional[ProbsType] = None)

The Measure Z gate.

Parameters
  • *q (int) – id numbers of the qubits to measure. It is possible to measure multiple qubits using gates.M(0, 1, 2, ...). If the qubits to measure are held in an iterable (eg. list) the * operator can be used, for example gates.M(*[0, 1, 4]) or gates.M(*range(5)).

  • register_name (str) – Optional name of the register to distinguish it from other registers when used in circuits.

  • collapse (bool) – Collapse the state vector after the measurement is performed. Can be used only for single shot measurements. If True the collapsed state vector is returned. If False the measurement result is returned.

  • p0 (dict) – Optional bitflip probability map. Can be: A dictionary that maps each measured qubit to the probability that it is flipped, a list or tuple that has the same length as the tuple of measured qubits or a single float number. If a single float is given the same probability will be used for all qubits.

  • p1 (dict) – Optional bitflip probability map for asymmetric bitflips. Same as p0 but controls the 1->0 bitflip probability. If p1 is None then p0 will be used both for 0->1 and 1->0 bitflips.

static einsum_string(qubits, nqubits, measuring=False)

Generates einsum string for partial trace of density matrices.

Parameters
  • qubits (list) – Set of qubit ids that are traced out.

  • nqubits (int) – Total number of qubits in the state.

  • measuring (bool) – If True non-traced-out indices are multiplied and the output has shape (nqubits - len(qubits),). If False the output has shape 2 * (nqubits - len(qubits),).

Returns

String to use in einsum for performing partial density of a density matrix.

symbol()

Returns symbol containing measurement outcomes for collapse=True gates.

add(gate: qibo.abstractions.gates.M)

Adds target qubits to a measurement gate.

This method is only used for creating the global measurement gate used by the models.Circuit. The user is not supposed to use this method and a ValueError is raised if he does so.

Parameters

gate – Measurement gate to add its qubits in the current gate.

Rotation X-axis (RX)

class qibo.abstractions.gates.RX(q, theta, trainable=True)

Rotation around the X-axis of the Bloch sphere.

Corresponds to the following unitary matrix

\[\begin{split}\begin{pmatrix} \cos \frac{\theta }{2} & -i\sin \frac{\theta }{2} \\ -i\sin \frac{\theta }{2} & \cos \frac{\theta }{2} \\ \end{pmatrix}\end{split}\]
Parameters

Rotation Y-axis (RY)

class qibo.abstractions.gates.RY(q, theta, trainable=True)

Rotation around the Y-axis of the Bloch sphere.

Corresponds to the following unitary matrix

\[\begin{split}\begin{pmatrix} \cos \frac{\theta }{2} & -\sin \frac{\theta }{2} \\ \sin \frac{\theta }{2} & \cos \frac{\theta }{2} \\ \end{pmatrix}\end{split}\]
Parameters

Rotation Z-axis (RZ)

class qibo.abstractions.gates.RZ(q, theta, trainable=True)

Rotation around the Z-axis of the Bloch sphere.

Corresponds to the following unitary matrix

\[\begin{split}\begin{pmatrix} e^{-i \theta / 2} & 0 \\ 0 & e^{i \theta / 2} \\ \end{pmatrix}\end{split}\]
Parameters

First general unitary (U1)

class qibo.abstractions.gates.U1(q, theta, trainable=True)

First general unitary gate.

Corresponds to the following unitary matrix

\[\begin{split}\begin{pmatrix} 1 & 0 \\ 0 & e^{i \theta} \\ \end{pmatrix}\end{split}\]
Parameters

Second general unitary (U2)

class qibo.abstractions.gates.U2(q, phi, lam, trainable=True)

Second general unitary gate.

Corresponds to the following unitary matrix

\[\begin{split}\frac{1}{\sqrt{2}} \begin{pmatrix} e^{-i(\phi + \lambda )/2} & -e^{-i(\phi - \lambda )/2} \\ e^{i(\phi - \lambda )/2} & e^{i (\phi + \lambda )/2} \\ \end{pmatrix}\end{split}\]
Parameters

Third general unitary (U3)

class qibo.abstractions.gates.U3(q, theta, phi, lam, trainable=True)

Third general unitary gate.

Corresponds to the following unitary matrix

\[\begin{split}\begin{pmatrix} e^{-i(\phi + \lambda )/2}\cos\left (\frac{\theta }{2}\right ) & -e^{-i(\phi - \lambda )/2}\sin\left (\frac{\theta }{2}\right ) \\ e^{i(\phi - \lambda )/2}\sin\left (\frac{\theta }{2}\right ) & e^{i (\phi + \lambda )/2}\cos\left (\frac{\theta }{2}\right ) \\ \end{pmatrix}\end{split}\]
Parameters

Two qubit gates

Controlled-NOT (CNOT)

class qibo.abstractions.gates.CNOT(q0, q1)

The Controlled-NOT gate.

Corresponds to the following unitary matrix

\[\begin{split}\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \\ \end{pmatrix}\end{split}\]
Parameters
  • q0 (int) – the control qubit id number.

  • q1 (int) – the target qubit id number.

decompose(*free, use_toffolis: bool = True) List[qibo.abstractions.abstract_gates.Gate]

Decomposes multi-control gates to gates supported by OpenQASM.

Decompositions are based on arXiv:9503016.

Parameters

free – Ids of free qubits to use for the gate decomposition.

Returns

List with gates that have the same effect as applying the original gate.

Controlled-phase (CZ)

class qibo.abstractions.gates.CZ(q0, q1)

The Controlled-Phase gate.

Corresponds to the following unitary matrix

\[\begin{split}\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & -1 \\ \end{pmatrix}\end{split}\]
Parameters
  • q0 (int) – the control qubit id number.

  • q1 (int) – the target qubit id number.

Controlled-rotation X-axis (CRX)

class qibo.abstractions.gates.CRX(q0, q1, theta, trainable=True)

Controlled rotation around the X-axis for the Bloch sphere.

Corresponds to the following unitary matrix

\[\begin{split}\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & \cos \frac{\theta }{2} & -i\sin \frac{\theta }{2} \\ 0 & 0 & -i\sin \frac{\theta }{2} & \cos \frac{\theta }{2} \\ \end{pmatrix}\end{split}\]
Parameters

Controlled-rotation Y-axis (CRY)

class qibo.abstractions.gates.CRY(q0, q1, theta, trainable=True)

Controlled rotation around the Y-axis for the Bloch sphere.

Corresponds to the following unitary matrix

\[\begin{split}\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & \cos \frac{\theta }{2} & -\sin \frac{\theta }{2} \\ 0 & 0 & \sin \frac{\theta }{2} & \cos \frac{\theta }{2} \\ \end{pmatrix}\end{split}\]

Note that this differs from the qibo.abstractions.gates.RZ gate.

Parameters

Controlled-rotation Z-axis (CRZ)

class qibo.abstractions.gates.CRZ(q0, q1, theta, trainable=True)

Controlled rotation around the Z-axis for the Bloch sphere.

Corresponds to the following unitary matrix

\[\begin{split}\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & e^{-i \theta / 2} & 0 \\ 0 & 0 & 0 & e^{i \theta / 2} \\ \end{pmatrix}\end{split}\]
Parameters

Controlled first general unitary (CU1)

class qibo.abstractions.gates.CU1(q0, q1, theta, trainable=True)

Controlled first general unitary gate.

Corresponds to the following unitary matrix

\[\begin{split}\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & e^{i \theta } \\ \end{pmatrix}\end{split}\]

Note that this differs from the qibo.abstractions.gates.CRZ gate.

Parameters

Controlled second general unitary (CU2)

class qibo.abstractions.gates.CU2(q0, q1, phi, lam, trainable=True)

Controlled second general unitary gate.

Corresponds to the following unitary matrix

\[\begin{split}\frac{1}{\sqrt{2}} \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & e^{-i(\phi + \lambda )/2} & -e^{-i(\phi - \lambda )/2} \\ 0 & 0 & e^{i(\phi - \lambda )/2} & e^{i (\phi + \lambda )/2} \\ \end{pmatrix}\end{split}\]
Parameters

Controlled third general unitary (CU3)

class qibo.abstractions.gates.CU3(q0, q1, theta, phi, lam, trainable=True)

Controlled third general unitary gate.

Corresponds to the following unitary matrix

\[\begin{split}\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & e^{-i(\phi + \lambda )/2}\cos\left (\frac{\theta }{2}\right ) & -e^{-i(\phi - \lambda )/2}\sin\left (\frac{\theta }{2}\right ) \\ 0 & 0 & e^{i(\phi - \lambda )/2}\sin\left (\frac{\theta }{2}\right ) & e^{i (\phi + \lambda )/2}\cos\left (\frac{\theta }{2}\right ) \\ \end{pmatrix}\end{split}\]
Parameters

Swap (SWAP)

class qibo.abstractions.gates.SWAP(q0, q1)

The swap gate.

Corresponds to the following unitary matrix

\[\begin{split}\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix}\end{split}\]
Parameters
  • q0 (int) – the first qubit to be swapped id number.

  • q1 (int) – the second qubit to be swapped id number.

fSim

class qibo.abstractions.gates.fSim(q0, q1, theta, phi, trainable=True)

The fSim gate defined in arXiv:2001.08343.

Corresponds to the following unitary matrix

\[\begin{split}\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos \theta & -i\sin \theta & 0 \\ 0 & -i\sin \theta & \cos \theta & 0 \\ 0 & 0 & 0 & e^{-i \phi } \\ \end{pmatrix}\end{split}\]
Parameters

fSim with general rotation

class qibo.abstractions.gates.GeneralizedfSim(q0, q1, unitary, phi, trainable=True)

The fSim gate with a general rotation.

Corresponds to the following unitary matrix

\[\begin{split}\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & R_{00} & R_{01} & 0 \\ 0 & R_{10} & R_{11} & 0 \\ 0 & 0 & 0 & e^{-i \phi } \\ \end{pmatrix}\end{split}\]
Parameters
  • q0 (int) – the first qubit to be swapped id number.

  • q1 (int) – the second qubit to be swapped id number.

  • unitary (np.ndarray) – Unitary that corresponds to the one-qubit rotation.

  • phi (float) – Angle for the |11> phase.

  • trainable (bool) – whether gate parameters can be updated using qibo.abstractions.circuit.AbstractCircuit.set_parameters() (default is True).

property parameters

Returns a tuple containing the current value of gate’s parameters.

Special gates

Toffoli

class qibo.abstractions.gates.TOFFOLI(q0, q1, q2)

The Toffoli gate.

Parameters
  • q0 (int) – the first control qubit id number.

  • q1 (int) – the second control qubit id number.

  • q2 (int) – the target qubit id number.

decompose(*free, use_toffolis: bool = True) List[qibo.abstractions.abstract_gates.Gate]

Decomposes multi-control gates to gates supported by OpenQASM.

Decompositions are based on arXiv:9503016.

Parameters

free – Ids of free qubits to use for the gate decomposition.

Returns

List with gates that have the same effect as applying the original gate.

congruent(use_toffolis: bool = True) List[qibo.abstractions.abstract_gates.Gate]

Congruent representation of TOFFOLI gate.

This is a helper method for the decomposition of multi-control X gates. The congruent representation is based on Sec. 6.2 of arXiv:9503016. The sequence of the gates produced here has the same effect as TOFFOLI with the phase of the |101> state reversed.

Parameters

use_toffolis – If True a single TOFFOLI gate is returned. If False the congruent representation is returned.

Returns

List with RY and CNOT gates that have the same effect as applying the original TOFFOLI gate.

Arbitrary unitary

class qibo.abstractions.gates.Unitary(unitary, *q, trainable=True, name=None)

Arbitrary unitary gate.

Parameters
  • unitary – Unitary matrix as a tensor supported by the backend. Note that there is no check that the matrix passed is actually unitary. This allows the user to create non-unitary gates.

  • *q (int) – Qubit id numbers that the gate acts on.

  • trainable (bool) – whether gate parameters can be updated using qibo.abstractions.circuit.AbstractCircuit.set_parameters() (default is True).

  • name (str) – Optional name for the gate.

Variational layer

class qibo.abstractions.gates.VariationalLayer(qubits: List[int], pairs: List[Tuple[int, int]], one_qubit_gate, two_qubit_gate, params: List[float], params2: Optional[List[float]] = None, trainable: bool = True, name: Optional[str] = None)

Layer of one-qubit parametrized gates followed by two-qubit entangling gates.

Performance is optimized by fusing the variational one-qubit gates with the two-qubit entangling gates that follow them and applying a single layer of two-qubit gates as 4x4 matrices.

Parameters
  • qubits (list) – List of one-qubit gate target qubit IDs.

  • pairs (list) – List of pairs of qubit IDs on which the two qubit gate act.

  • one_qubit_gate – Type of one qubit gate to use as the variational gate.

  • two_qubit_gate – Type of two qubit gate to use as entangling gate.

  • params (list) – Variational parameters of one-qubit gates as a list that has the same length as qubits. These gates act before the layer of entangling gates.

  • params2 (list) – Variational parameters of one-qubit gates as a list that has the same length as qubits. These gates act after the layer of entangling gates.

  • trainable (bool) – whether gate parameters can be updated using qibo.abstractions.circuit.AbstractCircuit.set_parameters() (default is True).

  • name (str) – Optional name for the gate. If None the name "VariationalLayer" will be used.

Example

import numpy as np
from qibo.models import Circuit
from qibo import gates
# generate an array of variational parameters for 8 qubits
theta = 2 * np.pi * np.random.random(8)
# define qubit pairs that two qubit gates will act
pairs = [(i, i + 1) for i in range(0, 7, 2)]
# define a circuit of 8 qubits and add the variational layer
c = Circuit(8)
c.add(gates.VariationalLayer(range(8), pairs, gates.RY, gates.CZ, theta))
# this will create an optimized version of the following circuit
c2 = Circuit(8)
c.add((gates.RY(i, th) for i, th in enumerate(theta)))
c.add((gates.CZ(i, i + 1) for i in range(7)))
property parameters

Returns a tuple containing the current value of gate’s parameters.

Flatten

class qibo.abstractions.gates.Flatten(coefficients)

Passes an arbitrary state vector in the circuit.

Parameters

coefficients (list) – list of the target state vector components. This can also be a tensor supported by the backend.

Callback gate

class qibo.abstractions.gates.CallbackGate(callback: Callback)

Calculates a qibo.core.callbacks.Callback at a specific point in the circuit.

This gate performs the callback calulation without affecting the state vector.

Parameters

callback (qibo.core.callbacks.Callback) – Callback object to calculate.

property nqubits: int

Number of qubits that this gate acts on.

Fusion gate

class qibo.abstractions.gates.FusedGate(*q)

Collection of gates that will be fused and applied as single gate during simulation.

This gate is constructed automatically by qibo.core.circuit.Circuit.fuse() and should not be used by user. qibo.abstractions.gates.FusedGate works with arbitrary number of target qubits however the backend implementation qibo.core.gates.FusedGate assumes two target qubits.


Channels

Channels are implemented in Qibo as additional gates and can be accessed from the qibo.gates module. Channels can be used on density matrices to perform noisy simulations. Channels that inherit qibo.abstractions.gates.UnitaryChannel can also be applied to state vectors using sampling and repeated execution. For more information on the use of channels to simulate noise we refer to How to perform noisy simulation? The following channels are currently implemented:

Partial trace

class qibo.abstractions.gates.PartialTrace(*q)

Collapses a density matrix by tracing out selected qubits.

Works only with density matrices (not state vectors) and implements the following transformation:

\[\mathcal{E}(\rho ) = (|0\rangle \langle 0|) _A \otimes \mathrm{Tr} _A (\rho )\]

where A denotes the subsystem of qubits that are traced out.

Parameters

q (int) – Qubit ids that will be traced-out and collapsed to the zero state. More than one qubits can be given.

Kraus channel

class qibo.abstractions.gates.KrausChannel(ops)

General channel defined by arbitrary Krauss operators.

Implements the following transformation:

\[\mathcal{E}(\rho ) = \sum _k A_k \rho A_k^\dagger\]

where A are arbitrary Kraus operators given by the user. Note that Kraus operators set should be trace preserving, however this is not checked. Simulation of this gate requires the use of density matrices. For more information on channels and Kraus operators please check J. Preskill’s notes.

Parameters

ops (list) – List of Kraus operators as pairs (qubits, Ak) where qubits refers the qubit ids that Ak acts on and Ak is the corresponding matrix as a np.ndarray or tf.Tensor.

Example

import numpy as np
from qibo.models import Circuit
from qibo import gates
# initialize circuit with 3 qubits
c = Circuit(3, density_matrix=True)
# define a sqrt(0.4) * X gate
a1 = np.sqrt(0.4) * np.array([[0, 1], [1, 0]])
# define a sqrt(0.6) * CNOT gate
a2 = np.sqrt(0.6) * np.array([[1, 0, 0, 0], [0, 1, 0, 0],
                              [0, 0, 0, 1], [0, 0, 1, 0]])
# define the channel rho -> 0.4 X{1} rho X{1} + 0.6 CNOT{0, 2} rho CNOT{0, 2}
channel = gates.KrausChannel([((1,), a1), ((0, 2), a2)])
# add the channel to the circuit
c.add(channel)

Unitary channel

class qibo.abstractions.gates.UnitaryChannel(p, ops, seed=None)

Channel that is a probabilistic sum of unitary operations.

Implements the following transformation:

\[\mathcal{E}(\rho ) = \left (1 - \sum _k p_k \right )\rho + \sum _k p_k U_k \rho U_k^\dagger\]

where U are arbitrary unitary operators and p are floats between 0 and 1. Note that unlike qibo.abstractions.gates.KrausChannel which requires density matrices, it is possible to simulate the unitary channel using state vectors and probabilistic sampling. For more information on this approach we refer to Using repeated execution.

Parameters
  • p (list) – List of floats that correspond to the probability that each unitary Uk is applied.

  • ops (list) – List of operators as pairs (qubits, Uk) where qubits refers the qubit ids that Uk acts on and Uk is the corresponding matrix as a np.ndarray/tf.Tensor. Must have the same length as the given probabilities p.

  • seed (int) – Optional seed for the random number generator when sampling instead of density matrices is used to simulate this gate.

Pauli noise channel

class qibo.abstractions.gates.PauliNoiseChannel(q, px=0, py=0, pz=0, seed=None)

Noise channel that applies Pauli operators with given probabilities.

Implements the following transformation:

\[\mathcal{E}(\rho ) = (1 - p_x - p_y - p_z) \rho + p_x X\rho X + p_y Y\rho Y + p_z Z\rho Z\]

which can be used to simulate phase flip and bit flip errors. This channel can be simulated using either density matrices or state vectors and sampling with repeated execution. See How to perform noisy simulation? for more information.

Parameters
  • q (int) – Qubit id that the noise acts on.

  • px (float) – Bit flip (X) error probability.

  • py (float) – Y-error probability.

  • pz (float) – Phase flip (Z) error probability.

  • seed (int) – Optional seed for the random number generator when sampling instead of density matrices is used to simulate this gate.

Reset channel

class qibo.abstractions.gates.ResetChannel(q, p0=0.0, p1=0.0, seed=None)

Single-qubit reset channel.

Implements the following transformation:

\[\mathcal{E}(\rho ) = (1 - p_0 - p_1) \rho + p_0 (|0\rangle \langle 0| \otimes \tilde{\rho }) + p_1 (|1\rangle \langle 1| \otimes \tilde{\rho })\]

with

\[\tilde{\rho } = \frac{\langle 0|\rho |0\rangle }{\mathrm{Tr}\langle 0|\rho |0\rangle}\]
Parameters
  • q (int) – Qubit id that the channel acts on.

  • p0 (float) – Probability to reset to 0.

  • p1 (float) – Probability to reset to 1.

  • seed (int) – Optional seed for the random number generator when sampling instead of density matrices is used to simulate this gate.

Thermal relaxation channel

class qibo.abstractions.gates.ThermalRelaxationChannel(q, t1, t2, time, excited_population=0, seed=None)

Single-qubit thermal relaxation error channel.

Implements the following transformation:

If \(T_1 \geq T_2\):

\[\mathcal{E} (\rho ) = (1 - p_z - p_0 - p_1)\rho + p_zZ\rho Z + p_0 (|0\rangle \langle 0| \otimes \tilde{\rho }) + p_1 (|1\rangle \langle 1| \otimes \tilde{\rho })\]

with

\[\tilde{\rho } = \frac{\langle 0|\rho |0\rangle }{\mathrm{Tr}\langle 0|\rho |0\rangle}\]

while if \(T_1 < T_2\):

\[\mathcal{E}(\rho ) = \mathrm{Tr} _\mathcal{X}\left [\Lambda _{\mathcal{X}\mathcal{Y}}(\rho _\mathcal{X} ^T \otimes \mathbb{I}_\mathcal{Y})\right ]\]

with

\[\begin{split}\Lambda = \begin{pmatrix} 1 - p_1 & 0 & 0 & e^{-t / T_2} \\ 0 & p_1 & 0 & 0 \\ 0 & 0 & p_0 & 0 \\ e^{-t / T_2} & 0 & 0 & 1 - p_0 \end{pmatrix}\end{split}\]

where \(p_0 = (1 - e^{-t / T_1})(1 - \eta )\) \(p_1 = (1 - e^{-t / T_1})\eta\) and \(p_z = 1 - e^{-t / T_1} + e^{-t / T_2} - e^{t / T_1 - t / T_2}\). Here \(\eta\) is the excited_population and \(t\) is the time, both controlled by the user. This gate is based on Qiskit’s thermal relaxation error channel.

Parameters
  • q (int) – Qubit id that the noise channel acts on.

  • t1 (float) – T1 relaxation time. Should satisfy t1 > 0.

  • t2 (float) – T2 dephasing time. Should satisfy t1 > 0 and t2 < 2 * t1.

  • time (float) – the gate time for relaxation error.

  • excited_population (float) – the population of the excited state at equilibrium. Default is 0.

  • seed (int) – Optional seed for the random number generator when sampling instead of density matrices is used to simulate this gate.


Hamiltonians

The main abstract Hamiltonian object of Qibo is:

class qibo.abstractions.hamiltonians.AbstractHamiltonian

Qibo abstraction for Hamiltonian objects.

abstract eigenvalues()

Computes the eigenvalues for the Hamiltonian.

abstract eigenvectors()

Computes a tensor with the eigenvectors for the Hamiltonian.

ground_state()

Computes the ground state of the Hamiltonian.

Uses the eigenvectors method and returns the lowest energy eigenvector.

abstract exp(a)

Computes a tensor corresponding to exp(-1j * a * H).

Parameters

a (complex) – Complex number to multiply Hamiltonian before exponentiation.

abstract expectation(state, normalize=False)

Computes the real expectation value for a given state.

Parameters
  • state (array) – the expectation state.

  • normalize (bool) – If True the expectation value is divided with the state’s norm squared.

Returns

Real number corresponding to the expectation value.

Matrix Hamiltonian

The first implementation of Hamiltonians uses the full matrix representation of the Hamiltonian operator in the computational basis. This matrix has size (2 ** nqubits, 2 ** nqubits) and therefore its construction is feasible only when number of qubits is small.

class qibo.abstractions.hamiltonians.MatrixHamiltonian(nqubits, matrix=None)

Abstract Hamiltonian based on full matrix representation.

Parameters
  • nqubits (int) – number of quantum bits.

  • matrix (np.ndarray) – Matrix representation of the Hamiltonian in the computational basis as an array of shape (2 ** nqubits, 2 ** nqubits).

  • numpy (bool) – If True the Hamiltonian is created using numpy as the calculation backend, otherwise the selected backend is used. Default option is numpy = False.

property matrix

Returns the full (2 ** nqubits, 2 ** nqubits) matrix representation.

class qibo.core.hamiltonians.Hamiltonian(nqubits, matrix)

Backend implementation of qibo.abstractions.hamiltonians.MatrixHamiltonian.

Parameters
  • nqubits (int) – number of quantum bits.

  • matrix (np.ndarray) – Matrix representation of the Hamiltonian in the computational basis as an array of shape (2 ** nqubits, 2 ** nqubits).

classmethod from_symbolic(symbolic_hamiltonian, symbol_map)

Creates a Hamiltonian from a symbolic Hamiltonian.

We refer to the How to define custom Hamiltonians using symbols? example for more details.

Parameters
  • symbolic_hamiltonian (sympy.Expr) – The full Hamiltonian written with symbols.

  • symbol_map (dict) – Dictionary that maps each symbol that appears in the Hamiltonian to a pair of (target, matrix).

Returns

A qibo.abstractions.hamiltonians.SymbolicHamiltonian object that implements the Hamiltonian represented by the given symbolic expression.

eigenvalues()

Computes the eigenvalues for the Hamiltonian.

eigenvectors()

Computes a tensor with the eigenvectors for the Hamiltonian.

exp(a)

Computes a tensor corresponding to exp(-1j * a * H).

Parameters

a (complex) – Complex number to multiply Hamiltonian before exponentiation.

expectation(state, normalize=False)

Computes the real expectation value for a given state.

Parameters
  • state (array) – the expectation state.

  • normalize (bool) – If True the expectation value is divided with the state’s norm squared.

Returns

Real number corresponding to the expectation value.

Symbolic Hamiltonian

Qibo allows the user to define Hamiltonians using sympy symbols. In this case the full Hamiltonian matrix is not constructed unless this is required. This makes the implementation more efficient for larger qubit numbers. For more information on constructing Hamiltonians using symbols we refer to the How to define custom Hamiltonians using symbols? example.

class qibo.abstractions.hamiltonians.SymbolicHamiltonian(ground_state=None)

Abstract Hamiltonian based on symbolic representation.

Unlike qibo.abstractions.hamiltonians.MatrixHamiltonian this object does not create the full (2 ** nqubits, 2 ** nqubits) Hamiltonian matrix leading to more efficient calculations. Note that the matrix is required and will be created automatically if specific methods, such as .eigenvectors() or .exp() are called.

property dense

Creates the equivalent qibo.abstractions.hamiltonians.MatrixHamiltonian.

property matrix

Returns the full (2 ** nqubits, 2 ** nqubits) matrix representation.

eigenvalues()

Computes the eigenvalues for the Hamiltonian.

eigenvectors()

Computes a tensor with the eigenvectors for the Hamiltonian.

ground_state()

Computes the ground state of the Hamiltonian.

Uses the eigenvectors method and returns the lowest energy eigenvector.

exp(a)

Computes a tensor corresponding to exp(-1j * a * H).

Parameters

a (complex) – Complex number to multiply Hamiltonian before exponentiation.

class qibo.core.hamiltonians.SymbolicHamiltonian(form=None, symbol_map={}, ground_state=None)

Backend implementation of qibo.abstractions.hamiltonians.SymbolicHamiltonian.

Calculations using symbolic Hamiltonians are either done directly using the given sympy expression as it is (form) or by parsing the corresponding terms (which are qibo.core.terms.SymbolicTerm objects). The latter approach is more computationally costly as it uses a sympy.expand call on the given form before parsing the terms. For this reason the terms are calculated only when needed, for example during Trotterization. The dense matrix of the symbolic Hamiltonian can be calculated directly from form without requiring terms calculation (see qibo.core.hamiltonians.SymbolicHamiltonian.calculate_dense() for details).

Parameters
  • form (sympy.Expr) – Hamiltonian form as a sympy.Expr. Ideally the Hamiltonian should be written using Qibo symbols. See How to define custom Hamiltonians using symbols? example for more details.

  • symbol_map (dict) – Dictionary that maps each sympy.Symbol to a tuple of (target qubit, matrix representation). This feature is kept for compatibility with older versions where Qibo symbols were not available and may be deprecated in the future. It is not required if the Hamiltonian is constructed using Qibo symbols. The symbol_map can also be used to pass non-quantum operator arguments to the symbolic Hamiltonian, such as the parameters in the qibo.hamiltonians.MaxCut() Hamiltonian.

  • ground_state (Callable) – Function with no arguments that returns the ground state of this Hamiltonian. This is useful in cases where the ground state is trivial and is used for initialization, for example the easy Hamiltonian in adiabatic evolution, however we would like to avoid constructing and diagonalizing the full Hamiltonian matrix only to find the ground state.

property terms

List of qibo.core.terms.HamiltonianTerm objects of which the Hamiltonian is a sum of.

expectation(state, normalize=False)

Computes the real expectation value for a given state.

Parameters
  • state (array) – the expectation state.

  • normalize (bool) – If True the expectation value is divided with the state’s norm squared.

Returns

Real number corresponding to the expectation value.

apply_gates(state, density_matrix=False)

Applies gates corresponding to the Hamiltonian terms to a given state.

Helper method for __matmul__.

circuit(dt, accelerators=None)

Circuit that implements a Trotter step of this Hamiltonian for a given time step dt.

When a qibo.core.hamiltonians.SymbolicHamiltonian is used for time evolution then Qibo will automatically perform this evolution using the Trotter of the evolution operator. This is done by automatically splitting the Hamiltonian to sums of commuting terms, following the description of Sec. 4.1 of arXiv:1901.05824. For more information on time evolution we refer to the How to simulate time evolution? example.

In addition to the abstract Hamiltonian models, Qibo provides the following pre-coded Hamiltonians:

Heisenberg XXZ

class qibo.hamiltonians.XXZ(nqubits, delta=0.5, dense=True)

Heisenberg XXZ model with periodic boundary conditions.

\[H = \sum _{i=0}^N \left ( X_iX_{i + 1} + Y_iY_{i + 1} + \delta Z_iZ_{i + 1} \right ).\]
Parameters

Example

from qibo.hamiltonians import XXZ
h = XXZ(3) # initialized XXZ model with 3 qubits

Non-interacting Pauli-X

class qibo.hamiltonians.X(nqubits, dense=True)

Non-interacting Pauli-X Hamiltonian.

\[H = - \sum _{i=0}^N X_i.\]
Parameters

Non-interacting Pauli-Y

class qibo.hamiltonians.Y(nqubits, dense=True)

Non-interacting Pauli-Y Hamiltonian.

\[H = - \sum _{i=0}^N Y_i.\]
Parameters

Non-interacting Pauli-Z

class qibo.hamiltonians.Z(nqubits, dense=True)

Non-interacting Pauli-Z Hamiltonian.

\[H = - \sum _{i=0}^N Z_i.\]
Parameters

Transverse field Ising model

class qibo.hamiltonians.TFIM(nqubits, h=0.0, dense=True)

Transverse field Ising model with periodic boundary conditions.

\[H = - \sum _{i=0}^N \left ( Z_i Z_{i + 1} + h X_i \right ).\]
Parameters

Max Cut

class qibo.hamiltonians.MaxCut(nqubits, dense=True)

Max Cut Hamiltonian.

\[H = - \sum _{i,j=0}^N \frac{1 - Z_i Z_j}{2}.\]
Parameters

Note

All pre-coded Hamiltonians can be created as qibo.core.hamiltonians.Hamiltonian using dense=True or qibo.core.hamiltonians.SymbolicHamiltonian using the dense=False. In the first case the Hamiltonian is created using its full matrix representation of size (2 ** n, 2 ** n) where n is the number of qubits that the Hamiltonian acts on. This matrix is used to calculate expectation values by direct matrix multiplication to the state and for time evolution by exact exponentiation. In contrast, when dense=False the Hamiltonian contains a more compact representation as a sum of local terms. This compact representation can be used to calculate expectation values via a sum of the local term expectations and time evolution via the Trotter decomposition of the evolution operator. This is useful for systems that contain many qubits for which constructing the full matrix is intractable.


Symbols

Qibo provides a basic set of symbols which inherit the sympy.Symbol object and can be used to construct qibo.abstractions.hamiltonians.SymbolicHamiltonian objects as described in the previous section.

class qibo.symbols.Symbol(q, matrix=None, name='Symbol', commutative=False)

Qibo specialization for sympy symbols.

These symbols can be used to create qibo.core.hamiltonians.SymbolicHamiltonian. See How to define custom Hamiltonians using symbols? for more details.

Example

from qibo import hamiltonians
from qibo.symbols import X, Y, Z
# construct a XYZ Hamiltonian on two qubits using Qibo symbols
form = X(0) * X(1) + Y(0) * Y(1) + Z(0) * Z(1)
ham = hamiltonians.SymbolicHamiltonian(form)
Parameters
  • q (int) – Target qubit id.

  • matrix (np.ndarray) – 2x2 matrix represented by this symbol.

  • name (str) – Name of the symbol which defines how it is represented in symbolic expressions.

  • commutative (bool) – If True the constructed symbols commute with each other. Default is False. This argument should be used with caution because quantum operators are not commutative objects and therefore switching this to True may lead to wrong results. It is useful for improving performance in symbolic calculations in cases where the user is sure that the operators participating in the Hamiltonian form are commuting (for example when the Hamiltonian consists of Z terms only).

property gate

Qibo gate that implements the action of the symbol on states.

full_matrix(nqubits)

Calculates the full dense matrix corresponding to the symbol as part of a bigger system.

Parameters

nqubits (int) – Total number of qubits in the system.

Returns

Matrix of dimension (2^nqubits, 2^nqubits) composed of the Kronecker product between identities and the symbol’s single-qubit matrix.

class qibo.symbols.X(q, commutative=False)

Qibo symbol for the Pauli-X operator.

Parameters

q (int) – Target qubit id.

class qibo.symbols.Y(q, commutative=False)

Qibo symbol for the Pauli-X operator.

Parameters

q (int) – Target qubit id.

class qibo.symbols.Z(q, commutative=False)

Qibo symbol for the Pauli-X operator.

Parameters

q (int) – Target qubit id.


States

Qibo circuits return qibo.abstractions.states.AbstractState objects when executed. By default, Qibo works as a wave function simulator in the sense that propagates the state vector through the circuit applying the corresponding gates. In this default usage the result of a circuit execution is the full final state vector which can be accessed via the tensor property of states. However for specific applications it is useful to have measurement samples from the final wave function, instead of its full vector form. To that end, qibo.abstractions.states.AbstractState provides the qibo.abstractions.states.AbstractState.samples() and qibo.abstractions.states.AbstractState.frequencies() methods.

In order to perform measurements the user has to add the measurement gate qibo.core.gates.M to the circuit and then execute providing a number of shots. If this is done, the qibo.abstractions.states.AbstractState returned by the circuit will contain the measurement samples.

For more information on measurements we refer to the How to perform measurements? example.

Abstract state

class qibo.abstractions.states.AbstractState(nqubits=None)

Abstract class for quantum states returned by model execution.

Parameters

nqubits (int) – Optional number of qubits in the state. If None then the number is calculated automatically from the tensor representation of the state.

property nqubits

Number of qubits in the state.

abstract property shape

Shape of the state’s tensor representation.

abstract property dtype

Type of state’s tensor representation.

property tensor

Tensor representation of the state in the computational basis.

abstract numpy()

State’s tensor representation as a numpy array.

state(numpy=False)

State’s tensor representation as an backend tensor.

Parameters

numpy (bool) – If True the returned tensor will be a numpy array, otherwise it will follow the backend tensor type. Default is False.

classmethod from_tensor(x, nqubits=None)

Constructs state from a tensor.

Parameters
  • x – Tensor representation of the state in the computational basis.

  • nqubits (int) – Optional number of qubits in the state. If None it is calculated automatically from the tensor representation shape.

abstract classmethod zero_state(nqubits)

Constructs the |00...0> state.

Parameters

nqubits (int) – Number of qubits in the state.

abstract classmethod plus_state(nqubits)

Constructs the |++...+> state.

Parameters

nqubits (int) – Number of qubits in the state.

copy()

Creates a copy of the state.

Note that this does not create a deep copy. The new state references to the same tensor representation for memory efficiency.

abstract to_density_matrix()

Transforms a pure quantum state to its density matrix form.

Returns

A qibo.abstractions.states.AbstractState object that contains the state in density matrix form.

abstract probabilities(qubits=None, measurement_gate=None)

Calculates measurement probabilities by tracing out qubits.

Exactly one of the following arguments should be given.

Parameters
  • qubits (list, set) – Set of qubits that are measured.

  • measurement_gate (qibo.abstractions.gates.M) – Measurement gate that contains the measured qubit details.

abstract measure(gate, nshots, registers=None)

Measures the state using a measurement gate.

Parameters
  • gate (qibo.abstractions.gates.M) – Measurement gate to use for measuring the state.

  • nshots (int) – Number of measurement shots.

  • registers (dict) – Dictionary that maps register names to the corresponding tuples of qubit ids.

abstract set_measurements(qubits, samples, registers=None)

Sets the state’s measurements using decimal samples.

Parameters
  • qubits (tuple) – Measured qubit ids.

  • samples (Tensor) – Tensor with decimal samples of the measurement results.

  • registers (dict) – Dictionary that maps register names to the corresponding tuples of qubit ids.

abstract samples(binary=True, registers=False)

Returns raw measurement samples.

Parameters
Returns

If binary is True

samples are returned in binary form as a tensor of shape (nshots, n_measured_qubits).

If binary is False

samples are returned in decimal form as a tensor of shape (nshots,).

If registers is True

samples are returned in a dict where the keys are the register names and the values are the samples tensors for each register.

If registers is False

a single tensor is returned which contains samples from all the measured qubits, independently of their registers.

abstract frequencies(binary=True, registers=False)

Returns the frequencies of measured samples.

Parameters
Returns

A collections.Counter where the keys are the observed values and the values the corresponding frequencies, that is the number of times each measured value/bitstring appears.

If binary is True

the keys of the Counter are in binary form, as strings of 0s and 1s.

If binary is False

the keys of the Counter are integers.

If registers is True

a dict of Counter s is returned where keys are the name of each register.

If registers is False

a single Counter is returned which contains samples from all the measured qubits, independently of their registers.

abstract apply_bitflips(p0, p1=None)

Applies bitflip noise to the measured samples.

Parameters
  • p0 – Bitflip probability map. Can be: A dictionary that maps each measured qubit to the probability that it is flipped, a list or tuple that has the same length as the tuple of measured qubits or a single float number. If a single float is given the same probability will be used for all qubits.

  • p1 – Probability of asymmetric bitflip. If p1 is given, p0 will be used as the probability for 0->1 and p1 as the probability for 1->0. If p1 is None the same probability p0 will be used for both bitflips.

abstract expectation(hamiltonian, normalize=False)

Calculates Hamiltonian expectation value with respect to the state.

Parameters
  • hamiltonian (qibo.abstractions.hamiltonians.Hamiltonian) – Hamiltonian object to calculate the expectation value of.

  • normalize (bool) – Normalize the result by dividing with the norm of the state. Default is False.

Distributed state

class qibo.core.states.DistributedState(circuit)

Data structure that holds the pieces of a state vector.

This is created automatically by qibo.core.distcircuit.DistributedCircuit which uses state pieces instead of the full state vector tensor to allow distribution to multiple devices. Using the DistributedState instead of the full state vector as a tensor avoids creating two copies of the state in the CPU memory and allows simulation of one more qubit.

The full state vector can be accessed using the state.vector or state.numpy() methods of the DistributedState. The DistributedState supports indexing as a standard array.

property dtype

Type of state’s tensor representation.

property tensor

Returns the full state vector as a tensor of shape (2 ** nqubits,).

This is done by merging the state pieces to a single tensor. Using this method will double memory usage.

create_pieces()

Creates qibo.core.states.DistributedState pieces on CPU.

assign_pieces(tensor)

Assigns state pieces from a given full state vector.

Parameters

tensor (K.Tensor) – The full state vector as a tensor supported by the underlying backend.

classmethod zero_state(circuit)

Creates |00...0> as a distributed state.

classmethod plus_state(circuit)

Creates |++...+> as a distributed state.

copy()

Creates a copy of the state.

Note that this does not create a deep copy. The new state references to the same tensor representation for memory efficiency.

probabilities(qubits=None, measurement_gate=None)

Calculates measurement probabilities by tracing out qubits.

Exactly one of the following arguments should be given.

Parameters
  • qubits (list, set) – Set of qubits that are measured.

  • measurement_gate (qibo.abstractions.gates.M) – Measurement gate that contains the measured qubit details.

Callbacks

Callbacks provide a way to calculate quantities on the state vector as it propagates through the circuit. Example of such quantity is the entanglement entropy, which is currently the only callback implemented in qibo.abstractions.callbacks.EntanglementEntropy. The user can create custom callbacks by inheriting the qibo.abstractions.callbacks.Callback class. The point each callback is calculated inside the circuit is defined by adding a qibo.abstractions.gates.CallbackGate. This can be added similarly to a standard gate and does not affect the state vector.

class qibo.abstractions.callbacks.Callback

Base callback class.

Callbacks should inherit this class and implement its _state_vector_call and _density_matrix_call methods.

Results of a callback can be accessed by indexing the corresponding object.

property nqubits

Total number of qubits in the circuit that the callback was added in.

Entanglement entropy

class qibo.abstractions.callbacks.EntanglementEntropy(partition: Optional[List[int]] = None, compute_spectrum: bool = False)

Von Neumann entanglement entropy callback.

\[S = \mathrm{Tr} \left ( \rho \log _2 \rho \right )\]
Parameters
  • partition (list) – List with qubit ids that defines the first subsystem for the entropy calculation. If partition is not given then the first subsystem is the first half of the qubits.

  • compute_spectrum (bool) – Compute the entanglement spectrum. Default is False.

Example

from qibo import models, gates, callbacks
# create entropy callback where qubit 0 is the first subsystem
entropy = callbacks.EntanglementEntropy([0], compute_spectrum=True)
# initialize circuit with 2 qubits and add gates
c = models.Circuit(2)
# add callback gates between normal gates
c.add(gates.CallbackGate(entropy))
c.add(gates.H(0))
c.add(gates.CallbackGate(entropy))
c.add(gates.CNOT(0, 1))
c.add(gates.CallbackGate(entropy))
# execute the circuit
final_state = c()
print(entropy[:])
# Should print [0, 0, 1] which is the entanglement entropy
# after every gate in the calculation.
print(entropy.spectrum)
# Print the entanglement spectrum.

Norm

class qibo.abstractions.callbacks.Norm

State norm callback.

\[\mathrm{Norm} = \left \langle \Psi | \Psi \right \rangle = \mathrm{Tr} (\rho )\]

Overlap

class qibo.abstractions.callbacks.Overlap

State overlap callback.

Calculates the overlap between the circuit state and a given target state:

\[\mathrm{Overlap} = |\left \langle \Phi | \Psi \right \rangle |\]
Parameters
  • state (np.ndarray) – Target state to calculate overlap with.

  • normalize (bool) – If True the states are normalized for the overlap calculation.

Energy

class qibo.abstractions.callbacks.Energy(hamiltonian: hamiltonians.Hamiltonian)

Energy expectation value callback.

Calculates the expectation value of a given Hamiltonian as:

\[\left \langle H \right \rangle = \left \langle \Psi | H | \Psi \right \rangle = \mathrm{Tr} (\rho H)\]

assuming that the state is normalized.

Parameters

hamiltonian (qibo.hamiltonians.Hamiltonian) – Hamiltonian object to calculate its expectation value.

Gap

class qibo.abstractions.callbacks.Gap(mode: Union[str, int] = 'gap', check_degenerate: bool = True)

Callback for calculating the gap of adiabatic evolution Hamiltonians.

Can also be used to calculate the Hamiltonian eigenvalues at each time step during the evolution. Note that this callback can only be added in qibo.evolution.AdiabaticEvolution models.

Parameters
  • mode (str/int) – Defines which quantity this callback calculates. If mode == 'gap' then the difference between ground state and first excited state energy (gap) is calculated. If mode is an integer, then the energy of the corresponding eigenstate is calculated.

  • check_degenerate (bool) – If True the excited state number is increased until a non-zero gap is found. This is used to find the proper gap in the case of degenerate Hamiltonians. This flag is relevant only if mode is 'gap'. Default is True.

Example

from qibo import callbacks, hamiltonians
from qibo.models import AdiabaticEvolution
# define easy and hard Hamiltonians for adiabatic evolution
h0 = hamiltonians.X(3)
h1 = hamiltonians.TFIM(3, h=1.0)
# define callbacks for logging the ground state, first excited
# and gap energy
ground = callbacks.Gap(0)
excited = callbacks.Gap(1)
gap = callbacks.Gap()
# define and execute the ``AdiabaticEvolution`` model
evolution = AdiabaticEvolution(h0, h1, lambda t: t, dt=1e-1,
                               callbacks=[gap, ground, excited])
final_state = evolution(final_time=1.0)
# print results
print(ground[:])
print(excited[:])
print(gap[:])

Solvers

Solvers are used to numerically calculate the time evolution of state vectors. They perform steps in time by integrating the time-dependent Schrodinger equation.

class qibo.solvers.BaseSolver(dt, hamiltonian)

Basic solver that should be inherited by all solvers.

Parameters
  • dt (float) – Time step size.

  • hamiltonian (qibo.abstractions.hamiltonians.Hamiltonian) – Hamiltonian object that the state evolves under.

property t

Solver’s current time.

class qibo.solvers.TrotterizedExponential(dt, hamiltonian)

Solver that uses Trotterized exponentials.

Created automatically from the qibo.solvers.Exponential if the given Hamiltonian object is a qibo.abstractions.hamiltonians.TrotterHamiltonian.

class qibo.solvers.Exponential(dt, hamiltonian)

Solver that uses the matrix exponential of the Hamiltonian:

\[U(t) = e^{-i H(t) \delta t}\]

Calculates the evolution operator in every step and thus is compatible with time-dependent Hamiltonians.

class qibo.solvers.RungeKutta4(dt, hamiltonian)

Solver based on the 4th order Runge-Kutta method.

class qibo.solvers.RungeKutta45(dt, hamiltonian)

Solver based on the 5th order Runge-Kutta method.

Optimizers

Optimizers are used automatically by the minimize methods of qibo.models.VQE and qibo.evolution.AdiabaticEvolution models. The user does not have to use any of the optimizer methods included in the current section, however the required options of each optimization method can be passed when calling the minimize method of the respective Qibo variational model.

qibo.optimizers.optimize(loss, initial_parameters, args=(), method='Powell', jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None, compile=False, processes=None)
Main optimization method. Selects one of the following optimizers:
Parameters
  • loss (callable) – Loss as a function of parameters and optional extra arguments. Make sure the loss function returns a tensor for method=sgd and numpy object for all the other methods.

  • initial_parameters (np.ndarray) – Initial guess for the variational parameters that are optimized.

  • args (tuple) – optional arguments for the loss function.

  • method (str) – Name of optimizer to use. Can be 'cma', 'sgd' or one of the Newtonian methods supported by qibo.optimizers.newtonian() and 'parallel_L-BFGS-B'. sgd is only available for backends based on tensorflow.

  • jac (dict) – Method for computing the gradient vector for scipy optimizers.

  • hess (dict) – Method for computing the hessian matrix for scipy optimizers.

  • hessp (callable) – Hessian of objective function times an arbitrary vector for scipy optimizers.

  • bounds (sequence or Bounds) – Bounds on variables for scipy optimizers.

  • constraints (dict) – Constraints definition for scipy optimizers.

  • tol (float) – Tolerance of termination for scipy optimizers.

  • callback (callable) – Called after each iteration for scipy optimizers.

  • options (dict) – Dictionary with options. See the specific optimizer bellow for a list of the supported options.

  • compile (bool) – If True the Tensorflow optimization graph is compiled. This is relevant only for the 'sgd' optimizer.

  • processes (int) – number of processes when using the parallel BFGS method.

Returns

Final best loss value; best parameters obtained by the optimizer; extra: optimizer-specific return object. For scipy methods it returns the OptimizeResult, for 'cma' the CMAEvolutionStrategy.result, and for 'sgd' the options used during the optimization.

Return type

(float, float, custom)

Example

import numpy as np
from qibo import gates, models
from qibo.optimizers import optimize

# create custom loss function
# make sure the return type matches the optimizer requirements.
def myloss(parameters, circuit):
    circuit.set_parameters(parameters)
    return np.square(np.sum(circuit())) # returns numpy array

# create circuit ansatz for two qubits
circuit = models.Circuit(2)
circuit.add(gates.RY(0, theta=0))

# optimize using random initial variational parameters
initial_parameters = np.random.uniform(0, 2, 1)
best, params, extra = optimize(myloss, initial_parameters, args=(circuit))

# set parameters to circuit
circuit.set_parameters(params)
qibo.optimizers.cmaes(loss, initial_parameters, args=(), options=None)

Genetic optimizer based on pycma.

Parameters
  • loss (callable) – Loss as a function of variational parameters to be optimized.

  • initial_parameters (np.ndarray) – Initial guess for the variational parameters.

  • args (tuple) – optional arguments for the loss function.

  • options (dict) – Dictionary with options accepted by the cma optimizer. The user can use import cma; cma.CMAOptions() to view the available options.

qibo.optimizers.newtonian(loss, initial_parameters, args=(), method='Powell', jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None, processes=None)

Newtonian optimization approaches based on scipy.optimize.minimize.

For more details check the scipy documentation.

Note

When using the method parallel_L-BFGS-B the processes option controls the number of processes used by the parallel L-BFGS-B algorithm through the multiprocessing library. By default processes=None, in this case the total number of logical cores are used. Make sure to select the appropriate number of processes for your computer specification, taking in consideration memory and physical cores. In order to obtain optimal results you can control the number of threads used by each process with the qibo.set_threads method. For example, for small-medium size circuits you may benefit from single thread per process, thus set qibo.set_threads(1) before running the optimization.

Parameters
  • loss (callable) – Loss as a function of variational parameters to be optimized.

  • initial_parameters (np.ndarray) – Initial guess for the variational parameters.

  • args (tuple) – optional arguments for the loss function.

  • method (str) – Name of method supported by scipy.optimize.minimize and 'parallel_L-BFGS-B' for a parallel version of L-BFGS-B algorithm.

  • jac (dict) – Method for computing the gradient vector for scipy optimizers.

  • hess (dict) – Method for computing the hessian matrix for scipy optimizers.

  • hessp (callable) – Hessian of objective function times an arbitrary vector for scipy optimizers.

  • bounds (sequence or Bounds) – Bounds on variables for scipy optimizers.

  • constraints (dict) – Constraints definition for scipy optimizers.

  • tol (float) – Tolerance of termination for scipy optimizers.

  • callback (callable) – Called after each iteration for scipy optimizers.

  • options (dict) – Dictionary with options accepted by scipy.optimize.minimize.

  • processes (int) – number of processes when using the parallel BFGS method.

qibo.optimizers.sgd(loss, initial_parameters, args=(), options=None, compile=False)

Stochastic Gradient Descent (SGD) optimizer using Tensorflow backpropagation.

See tf.keras.Optimizers for a list of the available optimizers.

Parameters
  • loss (callable) – Loss as a function of variational parameters to be optimized.

  • initial_parameters (np.ndarray) – Initial guess for the variational parameters.

  • args (tuple) – optional arguments for the loss function.

  • options (dict) –

    Dictionary with options for the SGD optimizer. Supports the following keys:

    • 'optimizer' (str, default: 'Adagrad'): Name of optimizer.

    • 'learning_rate' (float, default: '1e-3'): Learning rate.

    • 'nepochs' (int, default: 1e6): Number of epochs for optimization.

    • 'nmessage' (int, default: 1e3): Every how many epochs to print a message of the loss function.

Parallelism

We provide CPU multi-processing methods for circuit evaluation for multiple input states and multiple parameters for fixed input state.

When using the methods below the processes option controls the number of processes used by the parallel algorithms through the multiprocessing library. By default processes=None, in this case the total number of logical cores are used. Make sure to select the appropriate number of processes for your computer specification, taking in consideration memory and physical cores. In order to obtain optimal results you can control the number of threads used by each process with the qibo.set_threads method. For example, for small-medium size circuits you may benefit from single thread per process, thus set qibo.set_threads(1) before running the optimization.

Resources for parallel circuit evaluation.

qibo.parallel.parallel_execution(circuit, states, processes=None)

Execute circuit for multiple states.

Example

from qibo import models, set_threads
from qibo.parallel import parallel_execution
import numpy as np
# create circuit
nqubits = 22
circuit = models.QFT(nqubits)
# create random states
states = [ np.random.random(2**nqubits) for i in range(5)]
# set threads to 1 per process (optional, requires tuning)
set_threads(1)
# execute in parallel
results = parallel_execution(circuit, states, processes=2)
Parameters
  • circuit (qibo.models.Circuit) – the input circuit.

  • states (list) – list of states for the circuit evaluation.

  • processes (int) – number of processes for parallel evaluation.

Returns

Circuit evaluation for input states.

qibo.parallel.parallel_parametrized_execution(circuit, parameters, initial_state=None, processes=None)

Execute circuit for multiple parameters and fixed initial_state.

Example

from qibo import models, gates, set_threads
from qibo.parallel import parallel_parametrized_execution
import numpy as np
# create circuit
nqubits = 6
nlayers = 2
circuit = models.Circuit(nqubits)
for l in range(nlayers):
    circuit.add((gates.RY(q, theta=0) for q in range(nqubits)))
    circuit.add((gates.CZ(q, q+1) for q in range(0, nqubits-1, 2)))
    circuit.add((gates.RY(q, theta=0) for q in range(nqubits)))
    circuit.add((gates.CZ(q, q+1) for q in range(1, nqubits-2, 2)))
    circuit.add(gates.CZ(0, nqubits-1))
circuit.add((gates.RY(q, theta=0) for q in range(nqubits)))
# create random parameters
size = len(circuit.get_parameters())
parameters = [ np.random.uniform(0, 2*np.pi, size) for _ in range(10) ]
# set threads to 1 per process (optional, requires tuning)
set_threads(1)
# execute in parallel
results = parallel_parametrized_execution(circuit, parameters, processes=2)
Parameters
  • circuit (qibo.models.Circuit) – the input circuit.

  • parameters (list) – list of parameters for the circuit evaluation.

  • initial_state (np.array) – initial state for the circuit evaluation.

  • processes (int) – number of processes for parallel evaluation.

Returns

Circuit evaluation for input parameters.

Backends

The main calculation engine is defined in the abstract backend object qibo.backends.abstract.AbstractBackend. This object defines the methods required by all Qibo models to perform simulation.

Qibo currently provides two different calculation backends, one based on numpy and one based on Tensorflow. It is possible to define new backends by inheriting qibo.backends.abstract.AbstractBackend and implementing its abstract methods.

Both backends are supplemented by custom operators defined under which can be used to efficiently apply gates to state vectors or density matrices. These custom operators are shipped as the separate libraries qibojit and qibotf. We refer to Packages section for a complete list of the available computation backends and instructions on how to install each of these libraries on top of qibo.

Custom operators are much faster than implementations based on numpy or Tensorflow primitives (such as einsum) but do not support some features, such as automatic differentiation for backpropagation of variational circuits which is only supported by the native tensorflow backend.

The user can switch backends using

import qibo
qibo.set_backend("qibotf")
qibo.set_backend("numpy")

before creating any circuits or gates. The default backend is the first available from qibojit, qibotf, tensorflow, numpy.

For developers, we provide a configuration file in qibo/backends/profiles.yml containing the technical specifications for all backends supported by the Qibo team. If you are planning to introduce a new backend module for simulation or hardware, you can simply edit this profile file and include the reference to your new module. Alternatively, you can set a custom profile file by storing the file path in the QIBO_PROFILE environment variable before executing the code.

class qibo.backends.abstract.AbstractBackend
set_threads(nthreads)

Set number of OpenMP threads.

Parameters

num_threads (int) – number of threads.

get_cpu()

Returns default CPU device to use for OOM fallback.

cpu_fallback(func, *args)

Executes a function on CPU if the default devices raises OOM.

abstract to_numpy(x)

Convert tensor to numpy.

abstract to_complex(re, img)

Creates complex number from real numbers.

abstract cast(x, dtype='DTYPECPX')

Casts tensor to the given dtype.

abstract reshape(x, shape)

Reshapes tensor in the given shape.

abstract stack(x, axis=None)

Stacks a list of tensors to a single tensor.

abstract concatenate(x, axis=None)

Concatenates a list of tensor along a given axis.

abstract expand_dims(x, axis)

Creates a new axis of dimension one.

abstract copy(x)

Creates a copy of the tensor in memory.

abstract range(start, finish, step, dtype=None)

Creates a tensor of integers from start to finish.

abstract eye(dim, dtype='DTYPECPX')

Creates the identity matrix as a tensor.

abstract zeros(shape, dtype='DTYPECPX')

Creates tensor of zeros with the given shape and dtype.

abstract ones(shape, dtype='DTYPECPX')

Creates tensor of ones with the given shape and dtype.

abstract zeros_like(x)

Creates tensor of zeros with shape and dtype of the given tensor.

abstract ones_like(x)

Creates tensor of ones with shape and dtype of the given tensor.

abstract real(x)

Real part of a given complex tensor.

abstract imag(x)

Imaginary part of a given complex tensor.

abstract conj(x)

Elementwise complex conjugate of a tensor.

abstract mod(x)

Elementwise mod operation.

abstract right_shift(x, y)

Elementwise bitwise right shift.

abstract exp(x)

Elementwise exponential.

abstract sin(x)

Elementwise sin.

abstract cos(x)

Elementwise cos.

abstract pow(base, exponent)

Elementwise power.

abstract square(x)

Elementwise square.

abstract sqrt(x)

Elementwise square root.

abstract log(x)

Elementwise natural logarithm.

abstract abs(x)

Elementwise absolute value.

abstract expm(x)

Matrix exponential.

abstract trace(x)

Matrix trace.

abstract sum(x, axis=None)

Sum of tensor elements.

abstract matmul(x, y)

Matrix multiplication of two tensors.

abstract outer(x, y)

Outer (Kronecker) product of two tensors.

abstract kron(x, y)

Outer (Kronecker) product of two tensors.

abstract einsum(*args)

Generic tensor operation based on Einstein’s summation convention.

abstract tensordot(x, y, axes=None)

Generalized tensor product of two tensors.

abstract transpose(x, axes=None)

Tensor transpose.

abstract inv(x)

Matrix inversion.

abstract eigh(x)

Hermitian matrix eigenvalues and eigenvectors.

abstract eigvalsh(x)

Hermitian matrix eigenvalues.

abstract unique(x, return_counts=False)

Identifies unique elements in a tensor.

abstract less(x, y)

Compares the values of two tensors element-wise. Returns a bool tensor.

abstract array_equal(x, y)

Checks if two arrays are equal element-wise. Returns a single bool.

Used in qibo.tensorflow.hamiltonians.TrotterHamiltonian.construct_terms().

abstract squeeze(x, axis=None)

Removes axis of unit length.

abstract gather(x, indices=None, condition=None, axis=0)

Indexing of one-dimensional tensor.

abstract gather_nd(x, indices)

Indexing of multi-dimensional tensor.

abstract initial_state(nqubits, is_matrix=False)

Creates the default initial state |00...0> as a tensor.

abstract random_uniform(shape, dtype='DTYPE')

Samples array of given shape from a uniform distribution in [0, 1].

abstract sample_shots(probs, nshots)

Samples measurement shots from a given probability distribution.

Parameters
  • probs (Tensor) – Tensor with the probability distribution on the measured bitsrings.

  • nshots (int) – Number of measurement shots to sample.

Returns

Measurements in decimal as a tensor of shape (nshots,).

abstract sample_frequencies(probs, nshots)

Samples measurement frequencies from a given probability distribution.

Parameters
  • probs (Tensor) – Tensor with the probability distribution on the measured bitsrings.

  • nshots (int) – Number of measurement shots to sample.

Returns

Frequencies of measurements as a collections.Counter.

abstract compile(func)

Compiles the graph of a given function.

Relevant for Tensorflow, not numpy.

abstract device(device_name)

Used to execute code in specific device if supported by backend.

executing_eagerly()

Checks if we are in eager or compiled mode.

Relevant for the Tensorflow backends only.

abstract set_seed(seed)

Sets the seed for random number generation.

Parameters

seed (int) – Integer to use as seed.

abstract create_gate_cache(gate)

Calculates data required for applying gates to states.

These can be einsum index strings or tensors of qubit ids and it depends on the underlying backend.

Parameters

gate (qibo.abstractions.abstract_gates.BackendGate) – Gate object to calculate its cache.

Returns

Custom cache object that holds all the required data as attributes.

abstract state_vector_matrix_call(gate, state)

Applies gate to state vector using the gate’s unitary matrix representation.

This method is useful for the custom backend for which some gates do not require the unitary matrix.

Parameters
  • gate (qibo.abstractions.abstract_gates.BackendGate) – Gate object to apply to state.

  • state (Tensor) – State vector as a Tensor supported by this backend.

Returns

State vector after applying the gate as a Tensor.

abstract density_matrix_matrix_call(gate, state)

Applies gate to density matrix using the gate’s unitary matrix representation.

This method is useful for the custom backend for which some gates do not require the unitary matrix.

Parameters
  • gate (qibo.abstractions.abstract_gates.BackendGate) – Gate object to apply to state.

  • state (Tensor) – Density matrix as a Tensor supported by this backend.

Returns

Density matrix after applying the gate as a Tensor.

abstract density_matrix_half_matrix_call(gate, state)

Half gate application to density matrix using the gate’s unitary matrix representation.

abstract state_vector_collapse(gate, state, result)

Collapses state vector to a given result.

abstract density_matrix_collapse(gate, state, result)

Collapses density matrix to a given result.

abstract on_cpu()

Used as with K.on_cpu(): to perform following operations on CPU.

abstract cpu_tensor(x, dtype=None)

Creates backend tensors to be casted on CPU only.

Used by qibo.core.states.DistributedState to save state pieces on CPU instead of GPUs during a multi-GPU simulation.

abstract cpu_cast(x, dtype='DTYPECPX')

Forces tensor casting on CPU.

In contrast to simply K.cast which uses the current default device.

abstract cpu_assign(state, i, piece)

Assigns updated piece to a state object by transfering from GPU to CPU.

Parameters
  • state (qibo.core.states.DistributedState) – State object to assign the updated piece to.

  • i (int) – Index to assign the updated piece to.

  • piece (K.Tensor) – GPU tensor to transfer to CPU and assign to the piece of given index.

abstract transpose_state(pieces, state, nqubits, order)

Transposes distributed state pieces to obtain the full state vector.

Used by qibo.backends.abstract.AbstractMultiGpu.calculate_tensor().

abstract swap_pieces(piece0, piece1, new_global, nlocal)

Swaps two distributed state pieces in order to change the global qubits.

Useful to apply SWAP gates on distributed states.

abstract assert_allclose(value, target, rtol=1e-07, atol=0.0)

Check that two arrays are equal. Useful for testing.