Quantum gates and circuits
Quantum gates and circuits are essential when working on quantum computing. Here we describe basic treatment of them in QURI Parts.
Prerequisite
QURI Parts modules used in this tutorial: quri-parts-circuit
, quri-parts-core
, quri-parts-braket
, quri-parts-cirq
, quri-parts-qiskit
, quri-parts-qulacs
, and quri-parts-tket
. You can install them as follows:
!pip install "quri-parts[braket,cirq,qiskit,qulacs,tket]" pylatexenc
QuantumGate object
In QURI Parts, a quantum gate is represented by a QuantumGate
object (more precisely NamedTuple
). A QuantumGate
contains not only the kind of the gate but also some additional information such as gate parameters and qubits on which the gate acts. You can create gate objects using QuantumGate
:
from math import pi
from quri_parts.circuit import QuantumGate
gates = [
# X gate acting on qubit 0
QuantumGate("X", target_indices=(0,)),
# Rotation gate acting on qubit 1 with angle pi/3
QuantumGate("RX", target_indices=(1,), params=(pi/3,)),
# CNOT gate on control qubit 2 and target qubit 1
QuantumGate("CNOT", target_indices=(1,), control_indices=(2,)),
]
for gate in gates:
print(gate)
QuantumGate(name='X', target_indices=(0,), control_indices=(), classical_indices=(), params=(), pauli_ids=(), unitary_matrix=())
QuantumGate(name='RX', target_indices=(1,), control_indices=(), classical_indices=(), params=(1.0471975511965976,), pauli_ids=(), unitary_matrix=())
QuantumGate(name='CNOT', target_indices=(1,), control_indices=(2,), classical_indices=(), params=(), pauli_ids=(), unitary_matrix=())
However it is more convenient to use factory functions:
from quri_parts.circuit import X, RX, CNOT
gates = [
# X gate acting on qubit 0
X(0),
# Rotation gate acting on qubit 1 with angle pi/3
RX(1, pi/3),
# CNOT gate on control qubit 2 and target qubit 1
CNOT(2, 1),
]
for gate in gates:
print(gate)
QuantumGate(name='X', target_indices=(0,), control_indices=(), classical_indices=(), params=(), pauli_ids=(), unitary_matrix=())
QuantumGate(name='RX', target_indices=(1,), control_indices=(), classical_indices=(), params=(1.0471975511965976,), pauli_ids=(), unitary_matrix=())
QuantumGate(name='CNOT', target_indices=(1,), control_indices=(2,), classical_indices=(), params=(), pauli_ids=(), unitary_matrix=())
In QURI Parts single-qubit rotation gates are defined as follows:
where is called the angle of the gate.
You can access (but not set) attributes of a gate object:
from quri_parts.circuit import PauliRotation
x_gate = X(0)
print(f"name: {x_gate.name}, target: {x_gate.target_indices}")
rx_gate = RX(1, pi/3)
print(f"name: {rx_gate.name}, target: {rx_gate.target_indices}, angle: {rx_gate.params[0]}")
cnot_gate = CNOT(2, 1)
print(f"name: {cnot_gate.name}, control: {cnot_gate.control_indices}, target: {cnot_gate.target_indices}")
pauli_rot_gate = PauliRotation(target_indices=(0, 1, 2), pauli_ids=(1, 2, 3), angle=pi/3)
print(f"name: {pauli_rot_gate.name}, target: {pauli_rot_gate.target_indices}, pauli_ids: {pauli_rot_gate.pauli_ids}, angle: {pauli_rot_gate.params[0]}")
name: X, target: (0,)
name: RX, target: (1,), angle: 1.0471975511965976
name: CNOT, control: (2,), target: (1,)
name: PauliRotation, target: (0, 1, 2), pauli_ids: (1, 2, 3), angle: 1.0471975511965976
QuantumCircuit object
You can construct a quantum circuit by specifying the number of qubits used in the circuit as follows:
from quri_parts.circuit import QuantumCircuit
# Create a circuit for 3 qubits
circuit = QuantumCircuit(3)
# Add an already created QuantumGate object
circuit.add_gate(X(0))
# Or use methods to add gates
circuit.add_X_gate(0)
circuit.add_RX_gate(1, pi/3)
circuit.add_CNOT_gate(2, 1)
circuit.add_PauliRotation_gate(target_qubits=(0, 1, 2), pauli_id_list=(1, 2, 3), angle=pi/3)
A QuantumCircuit
object has several properties:
print("Qubit count:", circuit.qubit_count)
print("Circuit depth:", circuit.depth)
gates = circuit.gates # .gates returns the gates in the circuit as a sequence
print("# of gates in the circuit:", len(gates))
for gate in gates:
print(gate)