from math import pi
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.tools.visualization import matplotlib_circuit_drawer as drawer, qx_color_scheme

# We recommend the following options for Jupter notebook
%matplotlib inline

"""
Explanation: <img src="../../images/qiskit-heading.gif" alt="Note: In order for images to show up in this jupyter notebook you need to select File => Trusted Notebook" width="500 px" align="left">
matplotlib_circuit_drawer: matplotlib-based quantum circuit drawer
Qiskit-terra ver 0.5.5 intoduces matplotlib_circuit_drawer, which is a drop-in replacement of latex_circuit_drawer. If LaTeX is installed, circuit_drawer draws circuits by latex_circuit_drawer. Otherwise, it draws them by matplotlib_circuit_drawer. We explain the details of matplotlib_circuit_drawer in this notebook.
Contributors
Takashi Imamichi, Naoki Kanazawa
Setup
You first import Qiskit and matplotlib_drawer. We recommend the inline mode of matplotlib to draw circuits.
End of explanation
"""


# Create a Quantum Register called "q" with 3 qubits
qr = QuantumRegister(3, 'q')

# Create a Classical Register called "c" with 3 bits
cr = ClassicalRegister(3, 'c')

# Create a Quantum Circuit called involving "qr" and "cr"
circuit = QuantumCircuit(qr, cr)

circuit.x(qr[0]).c_if(cr, 3)
circuit.z(qr[0])
circuit.u2(pi/2, 2*pi/3, qr[1])

circuit.cu1(pi, qr[0], qr[1])

# Barrier to seperator the input from the circuit
circuit.barrier(qr[0])
circuit.barrier(qr[1])
circuit.barrier(qr[2])

# Toffoli gate from qubit 0,1 to qubit 2
circuit.ccx(qr[0], qr[1], qr[2])

# CNOT (Controlled-NOT) gate from qubit 0 to qubit 1
circuit.cx(qr[0], qr[1])

circuit.swap(qr[0], qr[2])

# measure gate from qr to cr
circuit.measure(qr, cr)

"""
Explanation: Create a quantum circuit
You can design a quantum circuit with quantum registers, quantum gates and classical registers.
End of explanation
"""


QASM_source = circuit.qasm()
print(QASM_source)

"""
Explanation: Extract OpenQASM
You can obtain a OpenQASM representation of your code.
End of explanation
"""


drawer(circuit)

drawer(circuit, basis='u1,u2,u3,id,cx', scale=1.0)

"""
Explanation: Visualize Circuit
You can visualize your circuit using matplotlib_drawer, which plots the unrolled circuit in the specified basis. You can adjust the size by specifying scale.
End of explanation
"""


my_style = {'plotbarrier': True}
drawer(circuit, style=my_style)

"""
Explanation: Use Stylesheet
You can configure your plot appearance by using style sheet written in dictionary format.
Show Barriers
You can visualize barriers by barrier key.
End of explanation
"""


my_style = {'cregbundle': True}
drawer(circuit, style=my_style)

"""
Explanation: Bundle Classical Registers
You can combine classical registers into a single line by cregbundle key.
End of explanation
"""


my_style = {'showindex': True}
drawer(circuit, style=my_style)

"""
Explanation: Show Index
Index of operation can be shown by index key.
End of explanation
"""


my_style = {'compress': True}
drawer(circuit, style=my_style)

"""
Explanation: Reduce Gap Between Gate
You can reduce redundant gaps between gates by compress key.
End of explanation
"""


my_style = {'fold': 6}
drawer(circuit, style=my_style)

"""
Explanation: Fold a Long Circuit
When the horizontal size of screen is limited, you can fold a circuit in multiple lines.
Maximum number of gate in a single line is specified by fold key (default: 20). If the value of key is less than 2, no folding option will be applied.
End of explanation
"""


my_style = {'usepiformat': True}
drawer(circuit, style=my_style)

"""
Explanation: Show Rotation Parameters in the unit of $\pi$
You can show rotation parameters in the unit of $\pi$ by usepiformat key.
End of explanation
"""


qr = QuantumRegister(1, 'q')
circuit_xyz = QuantumCircuit(qr)
circuit_xyz.x(qr[0])
circuit_xyz.y(qr[0])
circuit_xyz.z(qr[0])
drawer(circuit_xyz)

my_style = {'displaytext': {'x': '😺', 'y': '\Sigma', 'z': '✈'}}
drawer(circuit_xyz, style=my_style)

"""
Explanation: Use Emoji and LaTeX Symbols as Gate Symbols
You can use unicode characters and latex symbols supported by matplotlib for gates.
End of explanation
"""


qr = QuantumRegister(2, 'q')
circuit_cucz = QuantumCircuit(qr)
circuit_cucz.cz(qr[0], qr[1])
circuit_cucz.cu1(pi, qr[0], qr[1])
drawer(circuit_cucz)

my_style = {'latexdrawerstyle': False}
drawer(circuit_cucz, style=my_style)

"""
Explanation: Different style of gates: cz, cu1
CZ and CU1 gates can be visuarized in different formats by disable latexdrawerstyle key.
End of explanation
"""


qr = QuantumRegister(3, 'q')
cr = ClassicalRegister(3, 'c')
circuit_all = QuantumCircuit(qr, cr)

circuit_all.x(qr[0])
circuit_all.y(qr[0])
circuit_all.z(qr[0])
circuit_all.barrier(qr[0])
circuit_all.barrier(qr[1])
circuit_all.barrier(qr[2])
circuit_all.h(qr[0])
circuit_all.s(qr[0])
circuit_all.sdg(qr[0])
circuit_all.t(qr[0])
circuit_all.tdg(qr[0])
circuit_all.iden(qr[0])
circuit_all.reset(qr[0])
circuit_all.rx(pi, qr[0])
circuit_all.ry(pi, qr[0])
circuit_all.rz(pi, qr[0])
circuit_all.u0(pi, qr[0])
circuit_all.u1(pi, qr[0])
circuit_all.u2(pi, pi, qr[0])
circuit_all.u3(pi, pi, pi, qr[0])
circuit_all.swap(qr[0], qr[1])
circuit_all.cx(qr[0], qr[1])
circuit_all.cy(qr[0], qr[1])
circuit_all.cz(qr[0], qr[1])
circuit_all.ch(qr[0], qr[1])
circuit_all.cu1(pi, qr[0], qr[1])
circuit_all.cu3(pi, pi, pi, qr[0], qr[1])
circuit_all.crz(pi, qr[0], qr[1])
circuit_all.ccx(qr[0], qr[1], qr[2])
circuit_all.cswap(qr[0], qr[1], qr[2])

circuit_all.measure(qr, cr)

drawer(circuit_all)

"""
Explanation: All Options
You can use own style sheet to suit the result to your GUI. By combining above options, composer of IBM Q Experience can be reproduced.
End of explanation
"""


cmp_style = qx_color_scheme()
cmp_style

drawer(circuit_all, style=cmp_style)

"""
Explanation: You can configure the color scheme. Composer style sheet is prepared as qx_color_scheme.
End of explanation
"""


cmp_style.update({
    'usepiformat': True,
    'showindex': True,
    'cregbundle': True,
    'compress': True,
    'fold': 17
})
drawer(circuit_all, filename='circuit.pdf', style=cmp_style)

"""
Explanation: Save the circuit image to a file
The following line saves the image to 'circuit.pdf' by specifying a parameter filename.
End of explanation
"""


