Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

You down with plt (yeah you know me) [Issue 97] #119

Merged
merged 23 commits into from
May 9, 2019
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
624 changes: 624 additions & 0 deletions examples/state_and_process_plots.ipynb

Large diffs are not rendered by default.

28 changes: 25 additions & 3 deletions examples/tomography_process.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,35 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 7,
"metadata": {},
"outputs": [],
"outputs": [
{
"ename": "NameError",
"evalue": "name 'process_choi_ideal' is not defined",
"output_type": "error",
"traceback": [
"\u001b[0;31m--------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-7-cb314dff65b7>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mfig\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0max1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0max2\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msubplots\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfigsize\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m12\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0mplot_pauli_transfer_matrix\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mchoi2pauli_liouville\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mprocess_choi_ideal\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0max1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtitle\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'Ideal'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 7\u001b[0m \u001b[0mplot_pauli_transfer_matrix\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mchoi2pauli_liouville\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mprocess_choi_est\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0max2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtitle\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'Estimate'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtight_layout\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mNameError\u001b[0m: name 'process_choi_ideal' is not defined"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x12c740240>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"from forest.benchmarking.superoperator_tools import choi2pauli_liouville\n",
"from forest.benchmarking.tomography import plot_pauli_transfer_matrix\n",
"from forest.benchmarking.plotting.state_process import plot_pauli_transfer_matrix\n",
"\n",
"fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12,5))\n",
"plot_pauli_transfer_matrix(choi2pauli_liouville(process_choi_ideal), ax1, title='Ideal')\n",
Expand Down
98 changes: 97 additions & 1 deletion forest/benchmarking/plotting/hinton.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import matplotlib.pyplot as plt
import numpy as np
from typing import List
import matplotlib.pyplot as plt
from matplotlib import cm
import matplotlib as mpl
from matplotlib.colors import Normalize

ANGLE_MAPPER = cm.ScalarMappable(norm=Normalize(vmin=-np.pi, vmax=np.pi))


# Modified from the SciPy Cookbook.
def hinton(matrix, max_weight=1.0, ax=None):
"""Draw Hinton diagram for visualizing a weight matrix."""
ax = ax if ax is not None else plt.gca()
Expand All @@ -30,3 +33,96 @@ def hinton(matrix, max_weight=1.0, ax=None):
ax.set_ylim((-max_weight / 2, matrix.shape[1] - max_weight / 2))
ax.autoscale_view()
ax.invert_yaxis()



# From QuTiP which in turn modified the code from the SciPy Cookbook.
def _blob(x, y, w, w_max, area, cmap=None):
"""
Draws a square-shaped blob with the given area (< 1) at the given coordinates.
"""
hs = np.sqrt(area) / 2
xcorners = np.array([x - hs, x + hs, x + hs, x - hs])
ycorners = np.array([y - hs, y - hs, y + hs, y + hs])

plt.fill(xcorners, ycorners, color=cmap(int((w + w_max) * 256 / (2 * w_max))))


# Modified from QuTip (see https://bit.ly/2LrbayH ) which in turn modified the code from the
# SciPy Cookbook.
def hinton_real(matrix: np.ndarray,
max_weight: float = None,
xlabels: List[str] = None,
ylabels: List[str] = None,
title: str = None,
ax=None,
cmap=None,
label_top: bool = True):
'''
Draw Hinton diagram for visualizing a real valued weight matrix.

In the traditional Hinton diagram positive and negative values are represented by white and
black squares respectively. The size of each square represents the magnitude of each value.
The traditional Hinton diagram can be recovered by setting cmap = cm.Greys_r.

:param matrix: The matrix to be visualized.
:param max_weight: normalize size to this scalar.
:param xlabels: The labels for the operator basis.
:param ylabels: The labels for the operator basis.
:param title: The title for the plot.
:param ax: The matplotlib axes.
:param cmap: A matplotlib colormap to use when plotting.
:param label_top: If True, x-axis labels will be placed on top, otherwise they will appear
below the plot.
:return: A tuple of the matplotlib figure and axes instances used to produce the figure.
'''
if ax is None:
fig, ax = plt.subplots(1, 1, figsize=(8, 6))
if cmap is None:
cmap = cm.RdBu

if title and fig:
ax.set_title(title,y=1.1)

ax.set_aspect('equal', 'box')
ax.set_frame_on(False)

height, width = matrix.shape
if max_weight is None:
max_weight = 1.25 * max(abs(np.diag(np.matrix(matrix))))
if max_weight <= 0.0:
max_weight = 1.0

ax.fill(np.array([0, width, width, 0]), np.array([0, 0, height, height]), color=cmap(128))
for x in range(width):
for y in range(height):
_x = x + 1
_y = y + 1
if np.real(matrix[x, y]) > 0.0:
_blob(_x - 0.5, height - _y + 0.5, abs(matrix[x, y]), max_weight,
min(1, abs(matrix[x, y]) / max_weight), cmap=cmap)
else:
_blob(_x - 0.5, height - _y + 0.5, -abs(matrix[x, y]), max_weight,
min(1, abs(matrix[x, y]) / max_weight), cmap=cmap)

# color axis
if max_weight is None:
norm = mpl.colors.Normalize(-np.abs(matrix).max(), np.abs(matrix).max())
else:
norm = mpl.colors.Normalize(-np.abs(max_weight), max_weight)
cax, kw = mpl.colorbar.make_axes(ax, shrink=0.75, pad=.1)
mpl.colorbar.ColorbarBase(cax, norm=norm, cmap=cmap)
# x axis
ax.xaxis.set_major_locator(plt.IndexLocator(1, 0.5))
if xlabels:
ax.set_xticklabels(xlabels)
if label_top:
ax.xaxis.tick_top()
ax.tick_params(axis='x', labelsize=14)
# y axis
ax.yaxis.set_major_locator(plt.IndexLocator(1, 0.5))
if ylabels:
ax.set_yticklabels(list(reversed(ylabels)))
ax.tick_params(axis='y', labelsize=14)

return fig, ax
119 changes: 119 additions & 0 deletions forest/benchmarking/plotting/state_process.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import LinearSegmentedColormap

THREE_COLOR_MAP = ['#48737F', '#FFFFFF', '#D6619E']
rigetti_3_color_cm = LinearSegmentedColormap.from_list("Rigetti", THREE_COLOR_MAP[::-1], N=100)


def plot_pauli_rep_of_state(state_pl_basis, ax, labels, title):
"""
Visualize a quantum state in the Pauli-Liouville basis.

:param numpy.ndarray state_pl_basis: The quantum state represented in the Pauli-Liouville basis.
:param ax: The matplotlib axes.
:param labels: The labels for the operator basis states.
:param title: The title for the plot.

Examples
--------
from forest.benchmarking.superoperator_tools import *
from forest.benchmarking.utils import n_qubit_pauli_basis
# zero state in the (Z) computational basis
rho_std_basis = np.array([[1, 0], [0, 0]])
# change to Pauli-Liouville basis
n_qubits = 1
pl_basis = n_qubit_pauli_basis(n_qubits)
c2p = computational2pauli_basis_matrix(2*n_qubits)
rho_pl_basis = np.real(c2p@vec(rho_std_basis))
# plot
fig, ax = plt.subplots(1)
plot_pauli_rep_of_state(rho_pl_basis, ax, pl_basis.labels, 'Zero state |0>')
"""
if len(state_pl_basis.shape) == 1:
raise ValueError("You must pass in a (N by 1) or a (1 by N) numpy.ndarray")
if np.iscomplexobj(state_pl_basis):
raise ValueError("You must pass in a real vector")

im = ax.imshow(state_pl_basis, interpolation="nearest", cmap="RdBu", vmin=-1 / 2, vmax=1 / 2)
dim = len(labels)
# make the colorbar ticks look pretty
rows, cols = state_pl_basis.shape
if rows > cols:
cb = plt.colorbar(im, ax=ax, ticks=[-1 / 2, -1 / 4, 0, 1 / 4, 1 / 2])
ticklabs = cb.ax.get_yticklabels()
cb.ax.set_yticklabels(ticklabs, ha='right')
cb.ax.yaxis.set_tick_params(pad=35)
# axis labels etc
ax.set_xlabel("Coefficient")
ax.set_xticks([])
ax.set_yticks(range(dim))
ax.set_ylabel("Pauli Operator")
ax.set_yticklabels(labels)
else:
cb = plt.colorbar(im, ax=ax, ticks=[-1 / 2, -1 / 4, 0, 1 / 4, 1 / 2],
orientation="horizontal",
pad=0.22)
ax.set_ylabel("Coefficient")
ax.set_yticks([])
ax.set_xticks(range(dim))
ax.set_xlabel("Pauli Operator")
ax.set_xticklabels(labels)
ax.set_title(title)
ax.grid(False)


def plot_pauli_bar_rep_of_state(state_pl_basis, ax, labels, title):
"""
Visualize a quantum state in the Pauli-Liouville basis. The magnitude of the operator
coeffiences are represent by the height of a bar in the bargraph.

:param numpy.ndarray state_pl_basis: The quantum state represented in the Pauli-Liouville basis.
:param ax: The matplotlib axes.
:param labels: The labels for the operator basis states.
:param title: The title for the plot.
"""
dim = len(labels)
im = ax.bar(np.arange(dim) - .4, np.real(state_pl_basis), width=.8)
ax.set_xticks(range(dim))
ax.set_xlabel("Pauli Operator")
ax.set_ylabel("Coefficient")
ax.set_title(title)
ax.set_xticklabels(labels, rotation=45)
ax.grid(False)


def plot_pauli_transfer_matrix(ptransfermatrix, ax, labels=None, title='', fontsizes: int = 16):
"""
Visualize a quantum process using the Pauli-Liouville representation (aka the Pauli Transfer
Matrix) of the process.

:param numpy.ndarray ptransfermatrix: The Pauli Transfer Matrix
:param ax: The matplotlib axes.
:param labels: The labels for the operator basis states.
:param title: The title for the plot
:param fontsizes: Font size for axis labels
:return: The modified axis object.
:rtype: AxesSubplot
"""
im = ax.imshow(ptransfermatrix, interpolation="nearest", cmap="RdBu", vmin=-1, vmax=1)
if labels is None:
dim_squared = ptransfermatrix.shape[0]
num_qubits = np.int(np.log2(np.sqrt(dim_squared)))
labels = [''.join(x) for x in itertools.product('IXYZ', repeat=num_qubits)]
else:
dim_squared = len(labels)

cb = plt.colorbar(im, ax=ax, ticks=[-1, -3 / 4, -1 / 2, -1 / 4, 0, 1 / 4, 1 / 2, 3 / 4, 1])
ticklabs = cb.ax.get_yticklabels()
cb.ax.set_yticklabels(ticklabs, ha='right')
cb.ax.yaxis.set_tick_params(pad=35)
ax.set_xticks(range(dim_squared))
ax.set_xlabel("Input Pauli Operator", fontsize=fontsizes)
ax.set_yticks(range(dim_squared))
ax.set_ylabel("Output Pauli Operator", fontsize=fontsizes)
ax.set_title(title, fontsize= int(np.floor(1.2*fontsizes)))
ax.set_xticklabels(labels, rotation=45, fontsize=int(np.floor(0.7*fontsizes)))
ax.set_yticklabels(labels, fontsize=int(np.floor(0.7*fontsizes)))
ax.grid(False)
return ax
32 changes: 0 additions & 32 deletions forest/benchmarking/tomography.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
from operator import mul
from typing import Callable, Tuple, List, Optional, Union, Sequence

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import LinearSegmentedColormap
from scipy.linalg import logm, pinv, eigh

import forest.benchmarking.distance_measures as dm
Expand Down Expand Up @@ -801,33 +799,3 @@ def estimate_variance(results: List[ExperimentResult],
sample_estimate.append(np.real(functional(target_state, rho)))

return np.mean(sample_estimate), np.var(sample_estimate)


THREE_COLOR_MAP = ['#48737F', '#FFFFFF', '#D6619E']
rigetti_3_color_cm = LinearSegmentedColormap.from_list("Rigetti", THREE_COLOR_MAP[::-1], N=100)


def plot_pauli_transfer_matrix(ptransfermatrix, ax, title = ''):
"""
Visualize the Pauli Transfer Matrix of a process.
:param numpy.ndarray ptransfermatrix: The Pauli Transfer Matrix
:param ax: The matplotlib axes.
:param labels: The labels for the operator basis states.
:param title: The title for the plot
:return: The modified axis object.
:rtype: AxesSubplot
"""
im = ax.imshow(np.real(ptransfermatrix), interpolation="nearest", cmap=rigetti_3_color_cm, vmin=-1,vmax=1)
dim_squared = ptransfermatrix.shape[0]
num_qubits = np.int(np.log2(np.sqrt(dim_squared)))
labels = [''.join(x) for x in itertools.product('IXYZ', repeat=num_qubits)]
plt.colorbar(im, ax=ax)
ax.set_xticks(range(dim_squared))
ax.set_xlabel("Input Pauli Operator", fontsize=20)
ax.set_yticks(range(dim_squared))
ax.set_ylabel("Output Pauli Operator", fontsize=20)
ax.set_title(title, fontsize=25)
ax.set_xticklabels(labels, rotation=45)
ax.set_yticklabels(labels)
ax.grid(False)
return ax
Loading