qibolab.transpilers package#

Submodules#

qibolab.transpilers.abstract module#

qibolab.transpilers.abstract.find_gates_qubits_pairs(circuit: Circuit)[source]#

Translate qibo circuit into a list of pairs of qubits to be used by the transpiler.

Parameters:

circuit (qibo.models.Circuit) – circuit to be transpiled.

Returns:

list containing qubits targeted by two qubit gates

Return type:

translated_circuit (list)

class qibolab.transpilers.abstract.Placer(connectivity: Graph, *args)[source]#

Bases: ABC

A placer implements the initial logical-physical qubit mapping

class qibolab.transpilers.abstract.Router(connectivity: Graph, *args)[source]#

Bases: ABC

A router implements the mapping of a circuit on a specific hardware

class qibolab.transpilers.abstract.Transpiler[source]#

Bases: ABC

A transpiler is a transformation from a circuit to another circuit.

abstract is_satisfied(circuit: Circuit) bool[source]#

Checks if the circuit satisfies this transpiler’s requirements.

In some cases this is computationally easier to check than applying the transpilation transformations.

check_execution(original_circuit: Circuit, transpiled_circuit: Circuit | None = None)[source]#

Checks that the transpiled circuit agrees with the original using simulation.

Parameters:
  • original_circuit (qibo.models.Circuit) – Original circuit.

  • transpiled_circuit (qibo.models.Circuit) – Transpiled circuit. If not given, it will be calculated using qibolab.transpilers.abstract.Transpiler.transpile().

qibolab.transpilers.fusion module#

class qibolab.transpilers.fusion.Fusion(max_qubits: int = 1)[source]#

Bases: Transpiler

Apply gate fusion up to the given max_qubits.

max_qubits: int = 1#
is_satisfied(circuit)[source]#

Checks if the circuit satisfies this transpiler’s requirements.

In some cases this is computationally easier to check than applying the transpilation transformations.

class qibolab.transpilers.fusion.Rearrange(max_qubits: int = 1)[source]#

Bases: Fusion

Rearranges gates using qibo’s fusion algorithm.

May reduce number of SWAPs when fixing for connectivity but this has not been tested.

qibolab.transpilers.gate_decompositions module#

class qibolab.transpilers.gate_decompositions.GateDecompositions[source]#

Bases: object

Abstract data structure that holds decompositions of gates.

add(gate, decomposition)[source]#

Register a decomposition for a gate.

count_2q(gate)[source]#

Count the number of two-qubit gates in the decomposition of the given gate.

count_1q(gate)[source]#

Count the number of single qubit gates in the decomposition of the given gate.

qibolab.transpilers.gate_decompositions.translate_gate(gate, native_gates: NativeType)[source]#

Maps Qibo gates to a hardware native implementation.

Parameters:
  • gate (qibo.gates.abstract.Gate) – gate to be decomposed.

  • native_gates (list) – List of two qubit native gates supported by the quantum hardware (“CZ” and/or “iSWAP”).

Returns:

Shortest list of native gates

class qibolab.transpilers.gate_decompositions.NativeGates(two_qubit_natives: NativeType, translate_single_qubit: bool = True, verbose: bool = False)[source]#

Bases: Transpiler

Translates a circuit to native gates.

Parameters:
  • circuit (qibo.models.Circuit) – Circuit model to translate into native gates.

  • two_qubit_natives (list) – List of two qubit native gates supported by the quantum hardware (“CZ” and/or “iSWAP”).

Returns:

Equivalent circuit with native gates.

Return type:

new (qibo.models.Circuit)

two_qubit_natives: NativeType#
translate_single_qubit: bool = True#
verbose: bool = False#
tlog(message)[source]#

Print messages only if verbose was set to True.

is_satisfied(circuit)[source]#

Checks if a circuit can be executed on tii5q.

Parameters:
  • circuit (qibo.models.Circuit) – Circuit model to check.

  • two_qubit_natives (list) – List of two qubit native gates supported by the quantum hardware (“CZ” and/or “iSWAP”).

  • middle_qubit (int) – Hardware middle qubit.

  • verbose (bool) – If True it prints debugging log messages.

Returns True if the following conditions are satisfied:
  • Circuit does not contain more than two-qubit gates.

  • All one-qubit gates are I, Z, RZ or U3.

  • All two-qubit gates are CZ or iSWAP based on two_qubit_natives.

  • All two-qubit gates have qubit 0 as target or control.

otherwise returns False.

qibolab.transpilers.pipeline module#

class qibolab.transpilers.pipeline.Pipeline(transpilers: List[Transpiler], verbose: bool = False)[source]#

Bases: Transpiler

Transpiler consisting of a list of smaller transpilers that are applied sequentially.

transpilers: List[Transpiler]#
verbose: bool = False#
is_satisfied(circuit)[source]#

Checks if the circuit satisfies this transpiler’s requirements.

In some cases this is computationally easier to check than applying the transpilation transformations.

classmethod default(two_qubit_natives, middle_qubit=2, fuse_one_qubit=False, verbose=False)[source]#

Default transpiler used by qibolab.backends.QibolabBackend.

qibolab.transpilers.placer module#

exception qibolab.transpilers.placer.PlacementError[source]#

Bases: Exception

Raise for an error in the qubit placement

qibolab.transpilers.placer.assert_placement(circuit: Circuit, layout: dict) bool[source]#

Check if layout is correct and matches the number of qubits of the circuit.

Parameters:
  • circuit (qibo.models.Circuit) – Circuit model to check.

  • layout (dict) – physical to logical qubit mapping.

Raise PlacementError if the following conditions are not satisfied:
  • layout is written in the correct form.

  • layout matches the number of qubits in the circuit.

qibolab.transpilers.placer.assert_mapping_consistency(layout)[source]#

Check if layout is correct.

Parameters:

layout (dict) – physical to logical qubit mapping.

Raise PlacementError if layout is not written in the correct form.

class qibolab.transpilers.placer.Trivial(connectivity: Graph | None = None)[source]#

Bases: Placer

Place qubits according to the following simple notation: {‘q0’ : 0, ‘q1’ : 1, …, ‘qn’ : n}.

connectivity#

chip connectivity.

Type:

networkx.Graph

class qibolab.transpilers.placer.Custom(map, connectivity=None)[source]#

Bases: Placer

Define a custom initial qubit mapping.

map#

physical to logical qubit mapping,

Type:

list or dict

example [1,2,0] or {"q0"

1, “q1”:2, “q2”:0} to assign the

physical qubits 0;1;2 to the logical qubits 1;2;0 respectively.
connectivity#

chip connectivity.

Type:

networkx.Graph

class qibolab.transpilers.placer.Subgraph(connectivity)[source]#

Bases: Placer

Subgraph isomorphism qubit placer, NP-complete it can take a long time for large circuits. This initialization method may fail for very short circuits.

connectivity#

chip connectivity.

Type:

networkx.Graph

class qibolab.transpilers.placer.Random(connectivity, samples=100)[source]#

Bases: Placer

Random initialization with greedy policy, let a maximum number of 2-qubit gates can be applied without introducing any SWAP gate.

connectivity#

chip connectivity.

Type:

networkx.Graph

samples#

number of initial random layouts tested.

Type:

int

static cost(graph, gates_qubits_pairs)[source]#

Compute the cost associated to an initial layout as the lengh of the reduced circuit.

Parameters:
  • graph (networkx.Graph) – current hardware qubit mapping.

  • gates_qubits_pairs (list) – circuit representation.

Returns:

lengh of the reduced circuit.

Return type:

(int)

class qibolab.transpilers.placer.ReverseTraversal(connectivity: Graph, routing_algorithm: Router, depth=None)[source]#

Bases: Placer

Place qubits based on the algorithm proposed in https://doi.org/10.48550/arXiv.1809.02573. Works with ShortestPaths routing.

connectivity#

chip connectivity.

Type:

networkx.Graph

routing_algorithm#

routing algorithm.

Type:

qibolab.transpilers.routing.Transpiler

depth#

number of two qubit gates considered before finding initial layout. if ‘None’ just one backward step will be implemented. If depth is greater than the number of two qubit gates in the circuit, the circuit will be routed more than once. Example: on a circuit with four two qubit gates A-B-C-D using depth = 6, the routing will be performed on the circuit C-D-D-C-B-A.

Type:

int

assemble_circuit(circuit: Circuit)[source]#

Assemble a single circuit to apply Reverse Traversal placement based on depth. Example: for a circuit with four two qubit gates A-B-C-D using depth = 6, the function will return the circuit C-D-D-C-B-A.

Parameters:

circuit (qibo.models.Circuit) – circuit to be transpiled.

Returns:

assembled circuit to perform Reverse Traversal placement.

Return type:

new_circuit (qibo.models.Circuit)

routing_step(layout: dict, circuit: Circuit)[source]#

Perform routing of the circuit.

Parameters:
  • layout (dict) – intial qubit layout.

  • circuit (qibo.models.Circuit) – circuit to be routed.

qibolab.transpilers.routing module#

exception qibolab.transpilers.routing.ConnectivityError[source]#

Bases: Exception

Raise for an error in the connectivity

qibolab.transpilers.routing.assert_connectivity(connectivity: Graph, circuit: Circuit)[source]#

Assert if a circuit can be executed on Hardware. No gates acting on more than two qubits. All two qubit operations can be performed on hardware

Parameters:
  • circuit (qibo.models.Circuit) – circuit model to check.

  • connectivity (networkx.graph) – chip connectivity.

qibolab.transpilers.routing.remap_circuit(circuit: Circuit, qubit_map)[source]#

Map logical to physical qubits in a circuit.

Parameters:
  • circuit (qibo.models.Circuit) – qibo circuit to be remapped.

  • qubit_map (np.array) – new qubit mapping.

Returns:

transpiled circuit mapped with initial qubit mapping.

Return type:

new_circuit (qibo.models.Circuit)

class qibolab.transpilers.routing.ShortestPaths(connectivity: Graph, sampling_split=1.0, verbose=False)[source]#

Bases: Router

A class to perform initial qubit mapping and connectivity matching.

Properties:

sampling_split (float): fraction of paths tested (between 0 and 1).

connectivity#

chip connectivity.

Type:

networkx.Graph

verbose#

print info messages.

Type:

bool

initial_layout#

initial physical to logical qubit mapping

Type:

dict

added_swaps#

number of swaps added to the circuit to match connectivity.

Type:

int

_gates_qubits_pairs#

quantum circuit represented as a list (only 2 qubit gates).

Type:

list

_mapping#

circuit to physical qubit mapping during transpiling.

Type:

dict

_graph#

qubit mapped as nodes of the connectivity graph.

Type:

networkx.graph

_qubit_map#

circuit to physical qubit mapping during transpiling as vector.

Type:

np.array

_circuit_position#

position in the circuit.

Type:

int

transpiler_step(qibo_circuit)[source]#

Transpilation step. Find new mapping, add swap gates and apply gates that can be run with this configuration.

Parameters:

qibo_circuit (qibo.models.Circuit) – circuit to be transpiled.

first_transpiler_step(qibo_circuit)[source]#

First transpilation step. Apply gates that can be run with the initial qubit mapping.

Parameters:

qibo_circuit (qibo.models.Circuit) – circuit to be transpiled.

property sampling_split#
draw_connectivity()[source]#

Draw connectivity graph.

reduce(graph)[source]#

Reduce the circuit, delete a 2-qubit gate if it can be applied on the current configuration.

Parameters:

graph (networkx.Graph) – current hardware qubit mapping.

Returns:

reduced circuit.

Return type:

new_circuit (list)

map_list(path)[source]#

Return all possible walks of qubits, or a fraction, for a given path.

Parameters:

path (list) – path to move qubits.

Returns:

all possible walks of qubits, or a fraction of them based on self.sampling_split, for a given path. meeting_point_list (list): qubit meeting point for each path.

Return type:

mapping_list (list)

relocate()[source]#

A small greedy algorithm to decide which path to take, and how qubits should walk.

Returns:

best path to move qubits. meeting_point (int): qubit meeting point in the path.

Return type:

final_path (list)

initial_checks(qubits)[source]#

Initialize the transpiled circuit and check if it can be mapped to the defined connectivity.

Parameters:

qubits (int) – number of qubits in the circuit to be transpiled.

add_gates(qibo_circuit, matched_gates)[source]#

Add one and two qubit gates to transpiled circuit until connectivity is matched.

Parameters:
  • qibo_circuit (qibo.models.Circuit) – circuit to be transpiled.

  • matched_gates (int) – number of two qubit gates that can be applied with the current qubit mapping.

add_swaps(path, meeting_point)[source]#

Add swaps to the transpiled circuit to move qubits.

Parameters:
  • path (list) – path to move qubits.

  • meeting_point (int) – qubit meeting point in the path.

update_qubit_map()[source]#

Update the qubit mapping after adding swaps.

class qibolab.transpilers.routing.Sabre[source]#

Bases: Router

Routing algorithm proposed in https://doi.org/10.48550/arXiv.1809.02573

qibolab.transpilers.star_connectivity module#

qibolab.transpilers.star_connectivity.find_connected_qubit(qubits, queue, hardware_qubits)[source]#

Helper method for qibolab.transpilers.fix_connecivity().

Finds which qubit should be mapped to hardware middle qubit by looking at the two-qubit gates that follow.

class qibolab.transpilers.star_connectivity.StarConnectivity(middle_qubit: int, verbose: bool = False)[source]#

Bases: Transpiler

Transforms an arbitrary circuit to one that can be executed on hardware.

This transpiler produces a circuit that respects the following connectivity:

     q
     |
q -- q -- q
     |
     q

by adding SWAP gates when needed. It does not translate gates to native.

middle_qubit: int#

Qubit id of the qubit that is in the middle of the star.

verbose: bool = False#
tlog(message)[source]#

Print messages only if verbose was set to True.

is_satisfied(circuit, middle_qubit=2, verbose=True)[source]#

Checks if a circuit respects connectivity constraints.

Parameters:
  • circuit (qibo.models.Circuit) – Circuit model to check.

  • middle_qubit (int) – Hardware middle qubit.

  • verbose (bool) – If True it prints debugging log messages.

Returns True if the following conditions are satisfied:
  • Circuit does not contain more than two-qubit gates.

  • All two-qubit gates have qubit 0 as target or control.

otherwise returns False.

qibolab.transpilers.unitary_decompositions module#

qibolab.transpilers.unitary_decompositions.u3_decomposition(unitary)[source]#

Decomposes arbitrary one-qubit gates to U3.

Parameters:

unitary (np.ndarray) – Unitary 2x2 matrix to be decomposed.

Returns:

parameters of U3 gate.

Return type:

theta, phi, lam

qibolab.transpilers.unitary_decompositions.calculate_psi(unitary)[source]#

Solves the eigenvalue problem of UT_U.

See step (1) of Appendix A in arXiv:quant-ph/0011050.

Parameters:
  • unitary (np.ndarray) – Unitary matrix of the gate we are

  • basis. (decomposing in the computational) –

Returns:

Eigenvectors (in the computational basis) and eigenvalues of UT_U.

qibolab.transpilers.unitary_decompositions.schmidt_decompose(state)[source]#

Decomposes a two-qubit product state to its single-qubit parts.

qibolab.transpilers.unitary_decompositions.calculate_single_qubit_unitaries(psi)[source]#

Calculates local unitaries that maps a maximally entangled basis to the magic basis.

See Lemma 1 of Appendix A in arXiv:quant-ph/0011050.

Parameters:

psi (np.ndarray) – Maximally entangled two-qubit states that define a basis.

Returns:

Local unitaries UA and UB that map the given basis to the magic basis.

qibolab.transpilers.unitary_decompositions.calculate_diagonal(unitary, ua, ub, va, vb)[source]#

Calculates Ud matrix that can be written as exp(-iH).

See Eq. (A1) in arXiv:quant-ph/0011050. Ud is diagonal in the magic and Bell basis.

qibolab.transpilers.unitary_decompositions.magic_decomposition(unitary)[source]#

Decomposes an arbitrary unitary to (A1) from arXiv:quant-ph/0011050.

qibolab.transpilers.unitary_decompositions.to_bell_diagonal(ud)[source]#

Transforms a matrix to the Bell basis and checks if it is diagonal.

qibolab.transpilers.unitary_decompositions.calculate_h_vector(ud_diag)[source]#

Finds h parameters corresponding to exp(-iH).

See Eq. (4)-(5) in arXiv:quant-ph/0307177.

qibolab.transpilers.unitary_decompositions.cnot_decomposition(q0, q1, hx, hy, hz)[source]#

Performs decomposition (6) from arXiv:quant-ph/0307177.

qibolab.transpilers.unitary_decompositions.cnot_decomposition_light(q0, q1, hx, hy)[source]#

Performs decomposition (24) from arXiv:quant-ph/0307177.

qibolab.transpilers.unitary_decompositions.two_qubit_decomposition(q0, q1, unitary)[source]#

Performs two qubit unitary gate decomposition (24) from arXiv:quant-ph/0307177.

Parameters:
  • q0 (int) – Target qubits

  • q1 (int) – Target qubits

  • unitary (np.ndarray) – Unitary 4x4 matrix we are decomposing.

Returns:

quant-ph/0307177

Return type:

list of gates implementing decomposition (24) from arXiv