Optimizing the QuantumProgram or Circuit

The pyqonvert package consists of a number of methods to optimize quantum circuits by reducing the number of gates in the circuit. These are packaged as Converters, hence applied using the convert function.

Available optimizers

  • IdentityRemover - optimizes a quantum circuit or QuantumProgram by eliminating gates that are identified as identity below a certain specified tolerance. This optimizer takes identity_tolerance as an input.
# Initialization
optimizer = IdentityRemover(identity_tolerance=1e-9)
  • MultipleRotationGateSimplifier - optimizes a quantum circuit or QuantumProgram by adding up identical rotation gates in separate DecompositionBlocks.
# Initialization
optimizer = MultipleRotationGateSimplifier()
  • CircuitParallelizer - optimizes a quantum circuit or QuantumProgram by grouping operations into parallel execution blocks. Each parallel execution block is terminated by a PragmaStopParallelBlock operation. The execution time of the parallel block is extracted from the properties of the input device.
# Initialization
optimizer = CircuitParallelizer()
  • SleepInserter - adds a PragmaSleep operation before or after a gate, depending on the user specified placement mode. The PragmaSleep will only be added to gates that involve at least one qubit from the input of the SleepInserter and are of the gate type specified in the input.
# Initialization
optimizer = SleepInserter(
    gates = ["PauliZ"],
    involved_qubits = [0,1],
    sleep_time = 2.5,
    placement = "after"
)

placement is an optional argument set to "after" by default.

  • NumericSingleQubitMultiplier - optimizes a quantum circuit or a QuantumProgram by multiplying non-symbolic single-qubit-gates. As an argument, it takes in identity_tolerance that specifies a threshold below which gates are neglected as identity.
# Initialization
optimizer = NumericSingleQubitMultiplier(identity_tolerance=1e-9)
  • VirtualZGateReplacement - applies virtual Z gate optimization. Provided that the natural two-qubit gate is diagonal in the Z-basis, the converter replaces RotateZ gates by virtual changes (rotations) of the qubit basis in the XY-Plane. This is done by replacing gates corresponding to rotation in XY-Plane with RotateXY gate.
# Initialization
optimizer = VirtualZGateReplacement()

By default, the converter adds RotateZ gates at the end to undo the changes made to the qubit basis. This behavior can be modified by using the function apply_final_rotz

optimizer = VirtualZGateReplacement().apply_final_rotz(False)

Note that if RotateXY gate is available in the device, the user is not required to use the VirtualZGateReplacement converter. Simply running the gate decomposition routine produces the same effect as the optimizer.

Example

We give an example where we apply a series of optimizations on a quantum circuit.

from pyqonvert.optimization import (
    IdentityRemover,
    NumericSingleQubitMultiplier,
    CircuitParallelizer,
)
from qoqo import devices, Circuit
from qoqo import operations as ops

# Initialize device
number_qubits = 2
device = devices.AllToAllDevice(
    number_qubits, ["RotateZ", "RotateX", "SingleQubitGate"], ["CNOT"], 0.5
)

# Initialize circuit
circuit = Circuit()
circuit += ops.RotateZ(0, 1e-6)
circuit += ops.RotateZ(0, 0.5)
circuit += ops.RotateX(1, -1.0)
circuit += ops.RotateX(1, 2.0)
circuit += ops.CNOT(0, 1)

# List of converters
converters = [IdentityRemover(1e-5), NumericSingleQubitMultiplier(1e-5), CircuitParallelizer()]

# Optimizations
for converter in converters:
    circuit = converter.convert(circuit, device, [])

optimized circuit Figure 1: Resulting circuit after the application of optimization converters.