import qiskit
qiskit.__version__

from qiskit.circuit.library import XGate, CZGate, RZGate
from qiskit.circuit import QuantumCircuit

XGate() is XGate() is XGate() is XGate() is XGate() is XGate() is XGate() is XGate() is XGate()

CZGate() is CZGate() is CZGate() is CZGate() is CZGate() is CZGate() is CZGate() is CZGate() is CZGate() is CZGate() is CZGate() is CZGate() is CZGate()

gate = XGate()
print(f"name: {gate.name}")
print(f"params: {gate.params}")
print(f"matrix:\n{gate.to_matrix()}")
print(f"definition:\n{gate.definition}")

gate = XGate()
print(f"name: {gate.name}")
print(f"params: {gate.params}")
print(f"matrix:\n{gate.to_matrix()}")
print(f"definition:\n{gate.definition}")

import math
RZGate(math.pi) is RZGate(math.pi / 2)

RZGate(math.pi) is RZGate(math.pi)

gate = XGate()
try:
    gate.label = "My bespoke x gate that gives me perfect results"
except TypeError as e:
    print(e)

gate = XGate().to_mutable()
gate.label = "My bespoke x gate that gives me perfect results"
labelled_gate = XGate(label="My bespoke x gate that gives me perfect results")
print(labelled_gate.mutable)
qc = QuantumCircuit(1)
qc.append(gate, [0])
qc.append(labelled_gate, [0])
print(qc)

from qiskit import passmanager

class ToyPassManager(passmanager.BasePassManager):
    """Synthetic example PassManager that takes input "programs" integers operates on them as strings and returns a final integer
    
    The transpiler's passmanager defines ``_passmanager_frontend`` as QuantumCircuit -> DAGCircuit and ``_passmanager_backend``
    as DAGCircuit -> QuantumCircuit
    """
    
    def _passmanager_frontend(self, input_program: int, **kwargs) -> str:
        """Convert input int to str "IR"""
        return str(input_program)

    def _passmanager_backend(self, passmanager_ir: str, in_program: int, **kwargs) -> int:
        """Convert str "IR" to output int"""
        return int(passmanager_ir)

class RemoveFive(passmanager.GenericPass):
    """Pass for ToyPassManager that removes the number 5 from a string "IR"""

    def run(self, passmanager_ir: str):
        return passmanager_ir.replace("5", "")

pm = ToyPassManager(RemoveFive())

pm.run([123456789, 12345, 555552])

from qiskit.providers.fake_provider import FakeNairobiV2
from qiskit import transpile

qc = QuantumCircuit(5)
qc.x(4)
qc.h(range(5))
qc.cx(4, range(4))
tqc = transpile(qc, FakeNairobiV2(), optimization_level=3)
tqc.draw('mpl', fold=-1)

tqc.layout.initial_virtual_layout(filter_ancillas=True)

tqc.layout.final_index_layout()

from qiskit.circuit.library import RealAmplitudes
from qiskit.quantum_info import SparsePauliOp
from qiskit.primitives import BackendEstimator
from qiskit.compiler import transpile

psi = RealAmplitudes(num_qubits=2, reps=2)
H1 = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
backend = FakeNairobiV2()
estimator = BackendEstimator(backend=backend, skip_transpilation=True)

thetas = [0, 1, 1, 2, 3, 5]
transpiled_psi = transpile(psi, backend, optimization_level=3)
# New in 0.45.0 inflate and permute:
print(f"original operator:\n{H1}\n")
permuted_op = H1.apply_layout(transpiled_psi.layout)
print(f"final layout: {transpiled_psi.layout.final_index_layout()}\n")
print(f"operator with layout applied:\n{permuted_op}\n")
res = estimator.run(transpiled_psi, permuted_op, thetas, shots=int(1e5)).result()
print(res)