Circuit fusion#
The gates contained in a circuit can be fused up to two-qubits using the
qibo.models.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.gates.special.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.
The fusion algorithm works as follows: First all gates in the circuit are
transformed to unmarked qibo.gates.special.FusedGate. The gates
are then processed in the order they were added in the circuit. For each gate
we identify the neighbors forth and back in time and attempt to fuse them to
the gate. Two gates can be fused if their total number of target qubits is
smaller than the fusion maximum qubits (specified by the user) and there are
no other gates between acting on the same target qubits. Gates that are fused
to others are marked. The new circuit queue contains the gates that remain
unmarked after the above operations finish.
Gates are processed 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.
The user can specify the maximum number of qubits in a fused gate using
the max_qubits flag in qibo.models.circuit.Circuit.fuse().
For example the following:
from qibo import Circuit, gates
circuit = Circuit(2)
circuit.add([gates.H(0), gates.H(1)])
circuit.add(gates.CZ(0, 1))
circuit.add([gates.X(0), gates.Y(1)])
fused_circuit = circuit.fuse()
will create a new circuit with a single qibo.gates.special.FusedGate
acting on (0, 1), while the following:
from qibo import Circuit, gates
circuit = Circuit(3)
circuit.add([gates.H(0), gates.H(1), gates.H(2)])
circuit.add(gates.CZ(0, 1))
circuit.add([gates.X(0), gates.Y(1), gates.Z(2)])
circuit.add(gates.CNOT(1, 2))
circuit.add([gates.H(0), gates.H(1), gates.H(2)])
fused_circuit = circuit.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)]