def plot_bloch_vector(bloch, title="", ax=None, figsize=None): """Plot the Bloch sphere. Plot a sphere, axes, the Bloch vector, and its projections onto each axis. Args: bloch (list[double]): array of three elements where [<x>, <y>, <z>] title (str): a string that represents the plot title ax (matplotlib.Axes): An Axes to use for rendering the bloch sphere figsize (tuple): Figure size in inches. Has no effect is passing `ax`. Returns: Figure: A matplotlib figure instance if `ax = None`. Raises: ImportError: Requires matplotlib. """ if not HAS_MATPLOTLIB: raise ImportError('Must have Matplotlib installed.') if figsize is None: figsize = (5, 5) B = Bloch(axes=ax) B.add_vectors(bloch) B.render(title=title) if ax is None: fig = B.fig fig.set_size_inches(figsize[0], figsize[1]) plt.close(fig) return fig return None
def plot_bloch_vector(bloch, title="", ax=None, figsize=None, coord_type="cartesian"): """Plot the Bloch sphere. Plot a sphere, axes, the Bloch vector, and its projections onto each axis. Args: bloch (list[double]): array of three elements where [<x>, <y>, <z>] (Cartesian) or [<r>, <theta>, <phi>] (spherical in radians) <theta> is inclination angle from +z direction <phi> is azimuth from +x direction title (str): a string that represents the plot title ax (matplotlib.axes.Axes): An Axes to use for rendering the bloch sphere figsize (tuple): Figure size in inches. Has no effect is passing ``ax``. coord_type (str): a string that specifies coordinate type for bloch (Cartesian or spherical), default is Cartesian Returns: Figure: A matplotlib figure instance if ``ax = None``. Raises: MissingOptionalLibraryError: Requires matplotlib. Example: .. jupyter-execute:: from qiskit.visualization import plot_bloch_vector %matplotlib inline plot_bloch_vector([0,1,0], title="New Bloch Sphere") """ if not HAS_MATPLOTLIB: raise MissingOptionalLibraryError( libname="Matplotlib", name="plot_bloch_vector", pip_install="pip install matplotlib", ) from qiskit.visualization.bloch import Bloch from matplotlib import get_backend from matplotlib import pyplot as plt if figsize is None: figsize = (5, 5) B = Bloch(axes=ax) if coord_type == "spherical": r, theta, phi = bloch[0], bloch[1], bloch[2] bloch[0] = r * np.sin(theta) * np.cos(phi) bloch[1] = r * np.sin(theta) * np.sin(phi) bloch[2] = r * np.cos(theta) B.add_vectors(bloch) B.render(title=title) if ax is None: fig = B.fig fig.set_size_inches(figsize[0], figsize[1]) if get_backend() in ["module://ipykernel.pylab.backend_inline", "nbAgg"]: plt.close(fig) return fig return None
def plot_bloch_sphere(bloch_vectors): """Given a list of Bloch vectors, plot them on the Bloch sphere Args: bloch_vectors (list): list of bloch vectors """ sphere = Bloch() sphere.add_points(np.transpose(bloch_vectors)) sphere.show()
def plot_bloch_vector(bloch, title="", ax=None, figsize=None): """Plot the Bloch sphere. Plot a sphere, axes, the Bloch vector, and its projections onto each axis. Args: bloch (list[double]): array of three elements where [<x>, <y>, <z>] title (str): a string that represents the plot title ax (matplotlib.axes.Axes): An Axes to use for rendering the bloch sphere figsize (tuple): Figure size in inches. Has no effect is passing ``ax``. Returns: Figure: A matplotlib figure instance if ``ax = None``. Raises: ImportError: Requires matplotlib. Example: .. jupyter-execute:: from qiskit.visualization import plot_bloch_vector %matplotlib inline plot_bloch_vector([0,1,0], title="New Bloch Sphere") """ if not HAS_MATPLOTLIB: raise ImportError('Must have Matplotlib installed. To install, run ' '"pip install matplotlib".') if figsize is None: figsize = (5, 5) B = Bloch(axes=ax) B.add_vectors(bloch) B.render(title=title) if ax is None: fig = B.fig fig.set_size_inches(figsize[0], figsize[1]) if get_backend() in [ 'module://ipykernel.pylab.backend_inline', 'nbAgg' ]: plt.close(fig) return fig return None
def visualize_transition(circuit, trace=False, saveas=None, fpg=100, spg=2): """ Creates animation showing transitions between states of a single qubit by applying quantum gates. Args: circuit (QuantumCircuit): Qiskit single-qubit QuantumCircuit. Gates supported are h,x, y, z, rx, ry, rz, s, sdg, t, tdg and u1. trace (bool): Controls whether to display tracing vectors - history of 10 past vectors at each step of the animation. saveas (str): User can choose to save the animation as a video to their filesystem. This argument is a string of path with filename and extension (e.g. "movie.mp4" to save the video in current working directory). fpg (int): Frames per gate. Finer control over animation smoothness and computiational needs to render the animation. Works well for tkinter GUI as it is, for jupyter GUI it might be preferable to choose fpg between 5-30. spg (int): Seconds per gate. How many seconds should animation of individual gate transitions take. Returns: IPython.core.display.HTML: If arg jupyter is set to True. Otherwise opens tkinter GUI and returns after the GUI is closed. Raises: ImportError: Must have Matplotlib (and/or IPython) installed. VisualizationError: Given gate(s) are not supported. """ try: from IPython.display import HTML has_ipython = True except ImportError: has_ipython = False try: import matplotlib from matplotlib import pyplot as plt from matplotlib import animation from mpl_toolkits.mplot3d import Axes3D from qiskit.visualization.bloch import Bloch from qiskit.visualization.exceptions import VisualizationError has_matplotlib = True except ImportError: has_matplotlib = False jupyter = False if ('ipykernel' in sys.modules) and ('spyder' not in sys.modules): jupyter = True if not has_matplotlib: raise ImportError("Must have Matplotlib installed.") if not has_ipython and jupyter is True: raise ImportError("Must have IPython installed.") if len(circuit.qubits) != 1: raise VisualizationError("Only one qubit circuits are supported") frames_per_gate = fpg time_between_frames = (spg * 1000) / fpg # quaternions of gates which don't take parameters gates = dict() gates['x'] = ('x', _Quaternion.from_axisangle(np.pi / frames_per_gate, [1, 0, 0]), '#1abc9c') gates['y'] = ('y', _Quaternion.from_axisangle(np.pi / frames_per_gate, [0, 1, 0]), '#2ecc71') gates['z'] = ('z', _Quaternion.from_axisangle(np.pi / frames_per_gate, [0, 0, 1]), '#3498db') gates['s'] = ('s', _Quaternion.from_axisangle(np.pi / 2 / frames_per_gate, [0, 0, 1]), '#9b59b6') gates['sdg'] = ('sdg', _Quaternion.from_axisangle(-np.pi / 2 / frames_per_gate, [0, 0, 1]), '#8e44ad') gates['h'] = ('h', _Quaternion.from_axisangle(np.pi / frames_per_gate, _normalize([1, 0, 1])), '#34495e') gates['t'] = ('t', _Quaternion.from_axisangle(np.pi / 4 / frames_per_gate, [0, 0, 1]), '#e74c3c') gates['tdg'] = ('tdg', _Quaternion.from_axisangle(-np.pi / 4 / frames_per_gate, [0, 0, 1]), '#c0392b') implemented_gates = [ 'h', 'x', 'y', 'z', 'rx', 'ry', 'rz', 's', 'sdg', 't', 'tdg', 'u1' ] simple_gates = ['h', 'x', 'y', 'z', 's', 'sdg', 't', 'tdg'] list_of_circuit_gates = [] for gate in circuit._data: if gate[0].name not in implemented_gates: raise VisualizationError("Gate {} is not supported".format( gate[0].name)) if gate[0].name in simple_gates: list_of_circuit_gates.append(gates[gate[0].name]) else: theta = gate[0].params[0] rad = np.deg2rad(theta) if gate[0].name == 'rx': quaternion = _Quaternion.from_axisangle( rad / frames_per_gate, [1, 0, 0]) list_of_circuit_gates.append( ('rx:' + str(theta), quaternion, '#16a085')) elif gate[0].name == 'ry': quaternion = _Quaternion.from_axisangle( rad / frames_per_gate, [0, 1, 0]) list_of_circuit_gates.append( ('ry:' + str(theta), quaternion, '#27ae60')) elif gate[0].name == 'rz': quaternion = _Quaternion.from_axisangle( rad / frames_per_gate, [0, 0, 1]) list_of_circuit_gates.append( ('rz:' + str(theta), quaternion, '#2980b9')) elif gate[0].name == 'u1': quaternion = _Quaternion.from_axisangle( rad / frames_per_gate, [0, 0, 1]) list_of_circuit_gates.append( ('u1:' + str(theta), quaternion, '#f1c40f')) if len(list_of_circuit_gates) == 0: raise VisualizationError("Nothing to visualize.") starting_pos = _normalize(np.array([0, 0, 1])) fig = plt.figure(figsize=(5, 5)) _ax = Axes3D(fig) _ax.set_xlim(-10, 10) _ax.set_ylim(-10, 10) sphere = Bloch(axes=_ax) class Namespace: """Helper class serving as scope container""" def __init__(self): self.new_vec = [] self.last_gate = -2 self.colors = [] self.pnts = [] namespace = Namespace() namespace.new_vec = starting_pos def animate(i): sphere.clear() # starting gate count from -1 which is the initial vector gate_counter = (i - 1) // frames_per_gate if gate_counter != namespace.last_gate: namespace.pnts.append([[], [], []]) namespace.colors.append(list_of_circuit_gates[gate_counter][2]) # starts with default vector [0,0,1] if i == 0: sphere.add_vectors(namespace.new_vec) namespace.pnts[0][0].append(namespace.new_vec[0]) namespace.pnts[0][1].append(namespace.new_vec[1]) namespace.pnts[0][2].append(namespace.new_vec[2]) namespace.colors[0] = 'r' sphere.make_sphere() return _ax namespace.new_vec = list_of_circuit_gates[gate_counter][ 1] * namespace.new_vec namespace.pnts[gate_counter + 1][0].append(namespace.new_vec[0]) namespace.pnts[gate_counter + 1][1].append(namespace.new_vec[1]) namespace.pnts[gate_counter + 1][2].append(namespace.new_vec[2]) sphere.add_vectors(namespace.new_vec) if trace: # sphere.add_vectors(namespace.points) for point_set in namespace.pnts: sphere.add_points([point_set[0], point_set[1], point_set[2]]) sphere.vector_color = [list_of_circuit_gates[gate_counter][2]] sphere.point_color = namespace.colors sphere.point_marker = 'o' annotation_text = list_of_circuit_gates[gate_counter][0] annotationvector = [1.4, -0.45, 1.7] sphere.add_annotation(annotationvector, annotation_text, color=list_of_circuit_gates[gate_counter][2], fontsize=30, horizontalalignment='left') sphere.make_sphere() namespace.last_gate = gate_counter return _ax def init(): sphere.vector_color = ['r'] return _ax ani = animation.FuncAnimation( fig, animate, range(frames_per_gate * len(list_of_circuit_gates) + 1), init_func=init, blit=False, repeat=False, interval=time_between_frames) if saveas: ani.save(saveas, fps=30) if jupyter: # This is necessary to overcome matplotlib memory limit matplotlib.rcParams['animation.embed_limit'] = 50 return HTML(ani.to_jshtml()) plt.show() plt.close(fig) return None
def visualize_transition(circuit, trace=False, saveas=None, fpg=100, spg=2): """ Creates animation showing transitions between states of a single qubit by applying quantum gates. Args: circuit (QuantumCircuit): Qiskit single-qubit QuantumCircuit. Gates supported are h,x, y, z, rx, ry, rz, s, sdg, t, tdg and u1. trace (bool): Controls whether to display tracing vectors - history of 10 past vectors at each step of the animation. saveas (str): User can choose to save the animation as a video to their filesystem. This argument is a string of path with filename and extension (e.g. "movie.mp4" to save the video in current working directory). fpg (int): Frames per gate. Finer control over animation smoothness and computational needs to render the animation. Works well for tkinter GUI as it is, for jupyter GUI it might be preferable to choose fpg between 5-30. spg (int): Seconds per gate. How many seconds should animation of individual gate transitions take. Returns: IPython.core.display.HTML: If arg jupyter is set to True. Otherwise opens tkinter GUI and returns after the GUI is closed. Raises: MissingOptionalLibraryError: Must have Matplotlib (and/or IPython) installed. VisualizationError: Given gate(s) are not supported. """ try: from IPython.display import HTML has_ipython = True except ImportError: has_ipython = False try: import matplotlib from matplotlib import pyplot as plt from matplotlib import animation from mpl_toolkits.mplot3d import Axes3D from qiskit.visualization.bloch import Bloch from qiskit.visualization.exceptions import VisualizationError has_matplotlib = True except ImportError: has_matplotlib = False jupyter = False if ("ipykernel" in sys.modules) and ("spyder" not in sys.modules): jupyter = True if not has_matplotlib: raise MissingOptionalLibraryError( libname="Matplotlib", name="visualize_transition", pip_install="pip install matplotlib", ) if not has_ipython and jupyter is True: raise MissingOptionalLibraryError( libname="IPython", name="visualize_transition", pip_install="pip install ipython", ) if len(circuit.qubits) != 1: raise VisualizationError("Only one qubit circuits are supported") frames_per_gate = fpg time_between_frames = (spg * 1000) / fpg # quaternions of gates which don't take parameters gates = {} gates["x"] = ("x", _Quaternion.from_axisangle(np.pi / frames_per_gate, [1, 0, 0]), "#1abc9c") gates["y"] = ("y", _Quaternion.from_axisangle(np.pi / frames_per_gate, [0, 1, 0]), "#2ecc71") gates["z"] = ("z", _Quaternion.from_axisangle(np.pi / frames_per_gate, [0, 0, 1]), "#3498db") gates["s"] = ( "s", _Quaternion.from_axisangle(np.pi / 2 / frames_per_gate, [0, 0, 1]), "#9b59b6", ) gates["sdg"] = ( "sdg", _Quaternion.from_axisangle(-np.pi / 2 / frames_per_gate, [0, 0, 1]), "#8e44ad", ) gates["h"] = ( "h", _Quaternion.from_axisangle(np.pi / frames_per_gate, _normalize([1, 0, 1])), "#34495e", ) gates["t"] = ( "t", _Quaternion.from_axisangle(np.pi / 4 / frames_per_gate, [0, 0, 1]), "#e74c3c", ) gates["tdg"] = ( "tdg", _Quaternion.from_axisangle(-np.pi / 4 / frames_per_gate, [0, 0, 1]), "#c0392b", ) implemented_gates = ["h", "x", "y", "z", "rx", "ry", "rz", "s", "sdg", "t", "tdg", "u1"] simple_gates = ["h", "x", "y", "z", "s", "sdg", "t", "tdg"] list_of_circuit_gates = [] for gate in circuit._data: if gate[0].name not in implemented_gates: raise VisualizationError(f"Gate {gate[0].name} is not supported") if gate[0].name in simple_gates: list_of_circuit_gates.append(gates[gate[0].name]) else: theta = gate[0].params[0] if gate[0].name == "rx": quaternion = _Quaternion.from_axisangle(theta / frames_per_gate, [1, 0, 0]) list_of_circuit_gates.append(("rx:" + str(theta), quaternion, "#16a085")) elif gate[0].name == "ry": quaternion = _Quaternion.from_axisangle(theta / frames_per_gate, [0, 1, 0]) list_of_circuit_gates.append(("ry:" + str(theta), quaternion, "#27ae60")) elif gate[0].name == "rz": quaternion = _Quaternion.from_axisangle(theta / frames_per_gate, [0, 0, 1]) list_of_circuit_gates.append(("rz:" + str(theta), quaternion, "#2980b9")) elif gate[0].name == "u1": quaternion = _Quaternion.from_axisangle(theta / frames_per_gate, [0, 0, 1]) list_of_circuit_gates.append(("u1:" + str(theta), quaternion, "#f1c40f")) if len(list_of_circuit_gates) == 0: raise VisualizationError("Nothing to visualize.") starting_pos = _normalize(np.array([0, 0, 1])) fig = plt.figure(figsize=(5, 5)) if tuple(int(x) for x in matplotlib.__version__.split(".")) >= (3, 4, 0): _ax = Axes3D(fig, auto_add_to_figure=False) fig.add_axes(_ax) else: _ax = Axes3D(fig) _ax.set_xlim(-10, 10) _ax.set_ylim(-10, 10) sphere = Bloch(axes=_ax) class Namespace: """Helper class serving as scope container""" def __init__(self): self.new_vec = [] self.last_gate = -2 self.colors = [] self.pnts = [] namespace = Namespace() namespace.new_vec = starting_pos def animate(i): sphere.clear() # starting gate count from -1 which is the initial vector gate_counter = (i - 1) // frames_per_gate if gate_counter != namespace.last_gate: namespace.pnts.append([[], [], []]) namespace.colors.append(list_of_circuit_gates[gate_counter][2]) # starts with default vector [0,0,1] if i == 0: sphere.add_vectors(namespace.new_vec) namespace.pnts[0][0].append(namespace.new_vec[0]) namespace.pnts[0][1].append(namespace.new_vec[1]) namespace.pnts[0][2].append(namespace.new_vec[2]) namespace.colors[0] = "r" sphere.make_sphere() return _ax namespace.new_vec = list_of_circuit_gates[gate_counter][1] * namespace.new_vec namespace.pnts[gate_counter + 1][0].append(namespace.new_vec[0]) namespace.pnts[gate_counter + 1][1].append(namespace.new_vec[1]) namespace.pnts[gate_counter + 1][2].append(namespace.new_vec[2]) sphere.add_vectors(namespace.new_vec) if trace: # sphere.add_vectors(namespace.points) for point_set in namespace.pnts: sphere.add_points([point_set[0], point_set[1], point_set[2]]) sphere.vector_color = [list_of_circuit_gates[gate_counter][2]] sphere.point_color = namespace.colors sphere.point_marker = "o" annotation_text = list_of_circuit_gates[gate_counter][0] annotationvector = [1.4, -0.45, 1.7] sphere.add_annotation( annotationvector, annotation_text, color=list_of_circuit_gates[gate_counter][2], fontsize=30, horizontalalignment="left", ) sphere.make_sphere() namespace.last_gate = gate_counter return _ax def init(): sphere.vector_color = ["r"] return _ax ani = animation.FuncAnimation( fig, animate, range(frames_per_gate * len(list_of_circuit_gates) + 1), init_func=init, blit=False, repeat=False, interval=time_between_frames, ) if saveas: ani.save(saveas, fps=30) if jupyter: # This is necessary to overcome matplotlib memory limit matplotlib.rcParams["animation.embed_limit"] = 50 return HTML(ani.to_jshtml()) plt.show() plt.close(fig) return None