"""Concrete quantum circuit implementation backed by a Qiskit circuit."""
from __future__ import annotations
from typing import List
from qiskit import QuantumCircuit as QiskitQuantumCircuit
from qiskit.circuit.parametervector import ParameterVectorElement
from .base import QuantumCircuitBase
from .utils.qiskit_hash_functions import _circuit_key
[docs]
class QuantumCircuit(QuantumCircuitBase):
"""
Base class for quantum circuits for different quantum frameworks.
Args:
num_qubits (int): Number of qubits in the circuit
"""
def __init__(self, num_qubits: int, _native_circuit: QiskitQuantumCircuit | None = None):
super().__init__(num_qubits)
self._qiskit_circuit: QiskitQuantumCircuit = (
_native_circuit
if _native_circuit is not None
else QiskitQuantumCircuit(self._num_qubits)
)
[docs]
@classmethod
def from_quantum_circuit(cls, circuit: QuantumCircuitBase) -> QuantumCircuitBase:
"""Identity conversion for generic circuits."""
return circuit
@property
def qiskit_circuit(self) -> QiskitQuantumCircuit:
"""The underlying Qiskit circuit."""
return self._qiskit_circuit
@property
def num_qubits(self) -> int:
"""Return the number of qubits in the circuit."""
return self._qiskit_circuit.num_qubits
@property
def parameters(self) -> List[ParameterVectorElement]:
"""Return the free trainable parameters in the circuit."""
return list(self._qiskit_circuit.parameters)
@property
def num_parameters(self) -> int:
"""Return the number of free trainable parameters in the circuit."""
return len(self.parameters)
@property
def is_parameterized(self) -> bool:
"""Check if the wavefunction is parameterized."""
return len(self.parameters) > 0
[docs]
def draw(self) -> str:
"""Returns printable string representation of the circuit."""
raise NotImplementedError
[docs]
def h(self, qubits: int | List[int]):
"""Add hadamard gates"""
self._qiskit_circuit.h(qubits)
[docs]
def s(self, qubits: int | List[int]):
"""Add S gates"""
self._qiskit_circuit.s(qubits)
[docs]
def sdag(self, qubits: int | List[int]):
"""Add Sdag gates"""
self._qiskit_circuit.sdg(qubits)
[docs]
def t(self, qubits: int | List[int]):
"""Add T gates"""
self._qiskit_circuit.t(qubits)
[docs]
def tdag(self, qubits: int | List[int]):
"""Add Tdg gates"""
self._qiskit_circuit.tdg(qubits)
[docs]
def p(self, qubits: int | List[int], angle: float):
"""Add P gates"""
self._qiskit_circuit.p(angle, qubits)
[docs]
def cp(self, control_qubit: int, target_qubit: int, angle: float):
"""Add CP gates"""
self._qiskit_circuit.cp(angle, control_qubit, target_qubit)
[docs]
def x(self, qubits: int | List[int]):
"""Add X gates"""
self._qiskit_circuit.x(qubits)
[docs]
def y(self, qubits: int | List[int]):
"""Add Y gates"""
self._qiskit_circuit.y(qubits)
[docs]
def z(self, qubits: int | List[int]):
"""Add Z gates"""
self._qiskit_circuit.z(qubits)
[docs]
def rx(self, qubits: int | List[int], angle: float):
"""Add RX gates"""
self._qiskit_circuit.rx(angle, qubits)
[docs]
def ry(self, qubits: int | List[int], angle: float):
"""Add RY gates"""
self._qiskit_circuit.ry(angle, qubits)
[docs]
def rz(self, qubits: int | List[int], angle: float):
"""Add RZ gates"""
self._qiskit_circuit.rz(angle, qubits)
[docs]
def cx(self, control_qubit: int, target_qubit: int):
"""Add CNOT gates"""
self._qiskit_circuit.cx(control_qubit, target_qubit)
[docs]
def cy(self, control_qubit: int, target_qubit: int):
"""Add CY gates"""
self._qiskit_circuit.cy(control_qubit, target_qubit)
[docs]
def cz(self, control_qubit: int, target_qubit: int):
"""Add CZ gates"""
self._qiskit_circuit.cz(control_qubit, target_qubit)
[docs]
def cnot(self, control_qubit: int, target_qubit: int):
"""Add CNOT gates"""
self.cx(control_qubit, target_qubit)
[docs]
def ccx(self, control_qubit1: int, control_qubit2: int, target_qubit: int):
"""Add Toffoli (CCX) gates"""
self._qiskit_circuit.ccx(control_qubit1, control_qubit2, target_qubit)
[docs]
def toffoli(self, control_qubit1: int, control_qubit2: int, target_qubit: int):
"""Add Toffoli (CCX) gates"""
self.ccx(control_qubit1, control_qubit2, target_qubit)
[docs]
def ecr(self, control_qubit: int, target_qubit: int):
"""Add ECR gates"""
self._qiskit_circuit.ecr(control_qubit, target_qubit)
[docs]
def crx(self, control_qubit: int, target_qubit: int, angle: float):
"""Add CRX gates"""
self._qiskit_circuit.crx(angle, control_qubit, target_qubit)
[docs]
def cry(self, control_qubit: int, target_qubit: int, angle: float):
"""Add CRY gates"""
self._qiskit_circuit.cry(angle, control_qubit, target_qubit)
[docs]
def crz(self, control_qubit: int, target_qubit: int, angle: float):
"""Add CRZ gates"""
self._qiskit_circuit.crz(angle, control_qubit, target_qubit)
[docs]
def rxx(self, control_qubit: int, target_qubit: int, angle: float):
"""Add RXX gates"""
self._qiskit_circuit.rxx(angle, control_qubit, target_qubit)
[docs]
def ryy(self, control_qubit: int, target_qubit: int, angle: float):
"""Add RYY gates"""
self._qiskit_circuit.ryy(angle, control_qubit, target_qubit)
[docs]
def rzz(self, control_qubit: int, target_qubit: int, angle: float):
"""Add RZZ gates"""
self._qiskit_circuit.rzz(angle, control_qubit, target_qubit)
[docs]
def rzx(self, control_qubit: int, target_qubit: int, angle: float):
"""Add RZX gates"""
self._qiskit_circuit.rzx(angle, control_qubit, target_qubit)
[docs]
def swap(self, qubit1: int, qubit2: int):
"""Add SWAP gates"""
self._qiskit_circuit.swap(qubit1, qubit2)
[docs]
def barrier(self, qubits: int | List[int]):
"""Add barrier gates"""
self._qiskit_circuit.barrier(qubits)
[docs]
def measure(self):
"""Add measure gates"""
raise NotImplementedError
# pauli_string, pauli_evolution and controlled_pauli_evolution are
# inherited from QuantumCircuitBase.
[docs]
def compose(self, qc: QuantumCircuitBase, qubits: List[int]) -> "QuantumCircuit":
"""Compose two quantum circuits."""
if isinstance(qc, QuantumCircuit):
self._qiskit_circuit.compose(qc.qiskit_circuit, qubits, inplace=True)
return self
raise ValueError("The circuit to compose must be a QuantumCircuit object")
[docs]
def assign_parameters(self, parameters: dict):
"""Change parameters in the circuit.
Args:
parameters (np.array): parameters to assign to the circuit
"""
self._qiskit_circuit.assign_parameters(parameters, inplace=True)
[docs]
def invert(self) -> "QuantumCircuit":
"""Invert the circuit."""
return self.__class__(self._num_qubits, self._qiskit_circuit.inverse())
[docs]
def copy(self) -> "QuantumCircuit":
"""Return a copy of the circuit."""
return self.__class__(self._num_qubits, self._qiskit_circuit.copy())
[docs]
def circuit_metrics(self) -> dict:
"""count number of gates in the circuit"""
raise NotImplementedError
[docs]
def from_qasm(self, qasm: str) -> None:
"""Load the circuit from a qasm string"""
raise NotImplementedError
[docs]
def to_qasm(self) -> str:
"""Convert the circuit to a qasm string"""
raise NotImplementedError
def __hash__(self):
return hash(_circuit_key(self._qiskit_circuit))
def __str__(self):
return str(self._qiskit_circuit)
def __repr__(self):
return str(self)