from qiskit import QuantumCircuit
from qiskit.compiler import transpile
from qiskit.transpiler import PassManager

circ = QuantumCircuit(3)
circ.ccx(0, 1, 2)
circ.draw(output='mpl')

from qiskit.transpiler.passes import Unroller
pass_ = Unroller(['u1', 'u2', 'u3', 'cx'])
pm = PassManager(pass_)
new_circ = pm.run(circ)
new_circ.draw(output='mpl')

#同じパスの異なる実装
from qiskit.transpiler import CouplingMap, Layout
from qiskit.transpiler.passes import BasicSwap, LookaheadSwap, StochasticSwap

coupling = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]

circuit = QuantumCircuit(7)
circuit.h(3)
circuit.cx(0, 6)
circuit.cx(6, 0)
circuit.cx(0, 1)
circuit.cx(3, 1)
circuit.cx(3, 0)

coupling_map = CouplingMap(couplinglist=coupling)

bs = BasicSwap(coupling_map=coupling_map)
pass_manager = PassManager(bs)
basic_circ = pass_manager.run(circuit)

ls = LookaheadSwap(coupling_map=coupling_map)
pass_manager = PassManager(ls)
lookahead_circ = pass_manager.run(circuit)

ss = StochasticSwap(coupling_map=coupling_map)
pass_manager = PassManager(ss)
stochastic_circ = pass_manager.run(circuit)

circuit.draw(output='mpl')

lookahead_circ.draw(output='mpl')

stochastic_circ.draw(output='mpl')

basic_circ.draw(output='mpl')

#プリセット　パスマネージャー
import math
from qiskit.providers.fake_provider import FakeTokyo

backend=FakeTokyo()

qc = QuantumCircuit(10)

random_state = [
    1 / math.sqrt(4) * complex(0,1),
    1 / math.sqrt(8) * complex(1,0),
    0,
    0,
    0,
    0,
    0,
    0,
    1 / math.sqrt(8) * complex(1,0),
    1 / math.sqrt(8) * complex(0,1),
    0,
    0,
    0,
    0,
    1 / math.sqrt(4) * complex(1,0),
    1 / math.sqrt(8) * complex(1,0)]

qc.initialize(random_state, range(4))
qc.draw()

#異なる最適化
optimized_0 =transpile(qc, backend=backend, seed_transpiler=11, optimization_level=0)
print('gates = ', optimized_0.count_ops())
print('depth = ', optimized_0.depth())

optimized_1 = transpile(qc, backend=backend, seed_transpiler=11, optimization_level=1)
print('gates = ', optimized_1.count_ops())
print('depth = ', optimized_1.depth())

optimized_2 =transpile(qc, backend=backend,seed_transpiler=11, optimization_level=2)
print('gates =', optimized_2.count_ops())
print('depth =', optimized_2.depth())

optimized_3 =transpile(qc, backend=backend, seed_transpiler=11, optimization_level=3)
print('gates =', optimized_3.count_ops())
print('depth =', optimized_3.depth())

#有向非巡回グラフ
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit.dagcircuit import DAGCircuit
q = QuantumRegister(3, 'q')
c = ClassicalRegister(3, 'c')
circ = QuantumCircuit(q,c)
circ.h(q[0])
circ.cx(q[0], q[1])
circ.measure(q[0],c[0])
circ.rz(0.5, q[1]).c_if(c,2)
circ.draw(output='mpl')

