import numpy as np
from qiskit import QuantumCircuit, Aer
from qiskit.visualization import plot_bloch_multivector
from qiskit.quantum_info import Statevector

sim = Aer.get_backend("aer_simulator")

# 13の2進数表記
binary_13 = f"{13:05b}"
print(binary_13)

new_binary = binary_13[:2] + ("0" if binary_13[2] == "1" else "1") + binary_13[3:]
print(new_binary)


def flip_3rd_digid(integer):
    binary = f"{integer:05b}"
    new_binary = binary[:2] + ("0" if binary[2] == "1" else "1") + binary[3:]
    return new_binary

qc = QuantumCircuit(4, 2)  # A QuantumCircuit with 4 qubits and 2 classical bits``
# Xゲートを配置せよ
# <write your code>
qc.barrier()
# CNOTゲートを配置せよ
# <write your code>
qc.ccx(0, 1, 3)
qc.barrier()
qc.measure([2, 3], [0, 1])
qc.draw(output="mpl")

qc = QuantumCircuit(4, 2)  # A QuantumCircuit with 4 qubits and 2 classical bits``
# Xゲートを配置せよ
qc.x([0, 1])
qc.barrier()
# CNOTゲートを配置せよ
qc.cx(0, 2)
qc.cx(1, 2)
qc.ccx(0, 1, 3)
qc.barrier()
qc.measure([2, 3], [0, 1])
qc.draw(output="mpl")

qc = QuantumCircuit(1)  # A QuantumCircuit with 1 qubits
# 適切なゲートを配置せよ
# <write your code >
state = Statevector.from_instruction(qc)
plot_bloch_multivector(state)

qc = QuantumCircuit(1)  # A QuantumCircuit with 1 qubits
# 適切なゲートを配置せよ
qc.h(0)
state = Statevector.from_instruction(qc)
plot_bloch_multivector(state)

for state_label in ["+", "-"]:
    qc = QuantumCircuit(1,1)
    if state_label == "+":
        qc.initialize([1 / np.sqrt(2), 1 / np.sqrt(2)], 0)
    elif state_label == "-":
        qc.initialize([1 / np.sqrt(2), -1 / np.sqrt(2)], 0)
    qc.barrier()
    # 適切な測定基底をゲートを配置することで完成させよ
    # <write your code>
    qc.measure(0,0)
    counts = sim.run(qc).result().get_counts()
    print(f"|{state_label}> : ", "counts=",counts)
    qc.draw(output="mpl")

for state_label in ["+", "-"]:
    qc = QuantumCircuit(1,1)
    if state_label == "+":
        qc.initialize([1 / np.sqrt(2), 1 / np.sqrt(2)], 0)
    elif state_label == "-":
        qc.initialize([1 / np.sqrt(2), -1 / np.sqrt(2)], 0)
    qc.barrier()
    # 適切な測定基底をゲートを配置することで完成させよ
    qc.h(0)
    qc.measure(0,0)
    counts = sim.run(qc).result().get_counts()
    print(f"|{state_label}> : ", "counts=",counts)
    qc.draw(output="mpl")


for state_label in ["0", "1", "+", "-"]:
    for gate_label in ["X", "Z", "H", "ZH"]:
        qc = QuantumCircuit(1, 1)

        # 初期状態の設定
        if state_label == "1":
            qc.initialize([0, 1], 0)
        elif state_label == "+":
            qc.initialize([1 / np.sqrt(2), 1 / np.sqrt(2)], 0)
        elif state_label == "-":
            qc.initialize([1 / np.sqrt(2), -1 / np.sqrt(2)], 0)

        # ゲートの配置
        if gate_label =="X":
            qc.x(0)
        elif gate_label =="Z":
            qc.z(0)
        elif gate_label =="H":
            qc.h(0)
        elif gate_label =="ZH":
            qc.h(0)        
            qc.z(0)      
        # Statevectorは測定前に取得する必要がある
        state = Statevector.from_instruction(qc).data
        qc.measure(0, 0)
        counts = sim.run(qc).result().get_counts()
        print(f"{gate_label} |{state_label}> : ", "state=", state.round(3), "counts=",counts)
    print()

