Stacasso is a Python library for visualizing quantum computing circuits. See * Stacasso README, or view the project on GitHub for more information.
The original project notebook can be viewed online at Stacasso Guide (Notebook)
This notebook can be rendered to .html
with
time jupyter nbconvert --to html --execute stacasso_guide.ipynb
import datetime
print('Notebook last run',datetime.date.today())
Notebook last run 2021-06-06
Stacasso is extremely easy to use. For installation, see the README. Stacasso is typically imported with
import stacasso as so
There are two or three main functions, exposed to the user:
pprint( circuit, title=None, spacing=6 )
The "pretty-print" displays the circuit to the string like the standard print(circuit)
command, but add syntax highlighting. By default, the circuit is spaced wider than in the original cirq code; this is adjustable with the spacing
parameter.
highlight( circuit, title=None, spacing=6 )
The highlight command works like pretty-print, but returns the syntax highlighted code as an html
string. The string can copied directly into a markdown or .html
file, to render a syntax-highlighted version of the circuit.
illustrate( circuit, labels )
Stacasso can Illustrate the state (wavefuction) of the circuit as it executes. The simulation is done using cirq as a backend. The wavefunction is drawn after each moment (unitary transform), on grid representing the state-space ("Hilbert-space").
%load_ext autoreload
%autoreload 2
# import the Stacasso functions
import stacasso as so
import hlf
import tele
print('imported Stacasso, version',so.__version__)
imported Stacasso, version 0.0.3
# check to see if cirq is installed,
# and install with pip if not
try:
import cirq
print("imported cirq (already installed)")
except ImportError:
print("installing cirq...")
!pip install --quiet cirq
print("installed cirq.")
imported cirq (already installed)
# standard set of includes
import matplotlib.pyplot as plt
import time
import numpy as np
np.set_printoptions(precision=6)
%config InlineBackend.figure_formats = ['svg']
#import seaborn
# seaborn.set()
A Hadamard transformation put the bit into an equal superpositon of two states.
Upon measument, it will collapse to one of two states ("quantum coin flip").
This circuit is not useful in itself, but demonstrates the use of the H
gate to create superposition, one of the building blocks of quantum circuits.
# EXAMPLE - Quantum Random Number Generater
# first, make the circuit, using cirq
qrng_circuit = cirq.Circuit()
q0 = cirq.NamedQubit('qubit 0')
qrng_circuit.append(cirq.H(q0))
qrng_circuit.append(cirq.measure(q0))
# labeling the states is optional
labels = ['$\psi_0$', '', '$\psi_M$']
# print and illustrate with Stacasso
so.pprint( qrng_circuit, '"Quantum Random Number Generator (QRNG)"' )
so.illustrate( qrng_circuit, labels )
# plt.savefig( 'outputs/qrng_illustration_keep".svg')
"Quantum Random Number Generator (QRNG)"
qubit 0: ──────H──────M──────
# the syntax-highlighted circuit can be printed to the screen with `pprint`
# or returned as an html string with `highlight`, for embedding in other documents
qrng_circuit_html = so.highlight(qrng_circuit, '"Quantum Random Number Generator (QRNG)"')
print(qrng_circuit_html)
<div> <pre style="white-space:pre;font-size:medium;background:white;line-height:normal;font-family:monospace;"> <span style="color:Maroon">"Quantum Random Number Generator (QRNG)"</span><br><br> <span style="background-color:WhiteSmoke;color:Blue">qubit 0</span>: ──────H──────<span style="background-color:WhiteSmoke;color:Maroon;font-weight:bold">M</span>──────<br></pre> </div>
Bell States are made from maximially entangling two photons. It is one of the most fundamental quantum mechanical circuits.
# Bell Example
bell_circuit = so.make_bell_circuit()
# make labels (optional)
labels = ['$\psi_0$',
'',
'$\psi_{Bell}$',
'$\psi_M$']
so.pprint(bell_circuit,'"Bell State Circuit"')
so.illustrate(bell_circuit, labels)
# plt.savefig('outputs/bell_illustration.svg')
"Bell State Circuit"
q0: ──────H──────@──────M──────
│ │
q1: ─────────────X──────M──────
print(so.highlight(bell_circuit,"Bell State"))
<div> <pre style="white-space:pre;font-size:medium;background:white;line-height:normal;font-family:monospace;"> <span style="color:Maroon">Bell State</span><br><br> <span style="background-color:WhiteSmoke;color:Blue">q0</span>: ──────H──────<span style="color:MediumSlateBlue">@</span>──────<span style="background-color:WhiteSmoke;color:Maroon;font-weight:bold">M</span>──────<br> │ │<br> <span style="background-color:WhiteSmoke;color:DarkOrange">q1</span>: ─────────────X──────<span style="background-color:WhiteSmoke;color:Maroon;font-weight:bold">M</span>──────<br></pre> </div>
# quantum teleportation
import tele
gate = gate = cirq.X ** .3
tele_circuit = tele.make_quantum_teleportation_circuit(gate)
n_states = len(so.make_wavefunction_list( tele_circuit ))
labels = ['']*n_states
labels[0] = '$\psi_0$'
labels[2] = '$\psi_{Bell}$'
so.pprint(tele_circuit,'"Quantum Teleportation"')
so.illustrate(tele_circuit,offset_ends=True,labels=labels)
# plt.savefig('outputs/tele_illustration.svg')
"Quantum Teleportation"
0 (Ali): ──────H──────@─────────────────X─────────────M──────@─────────────
│ │ │ │
1 (Bob): ─────────────X─────────────────┼─────────────┼──────X──────@──────
│ │ │
2 (Msg): ────────────────────X^0.3──────@──────H──────M─────────────@──────
# print(so.highlight(tele_circuit,'"Quantum Teleportation"'))
hlf_circuit = hlf.make_interesting_circuit( n_qubits = 4 )
Creating an HLF 2D problem instance with 4 qubits 5 min size of L subspace finding interesting problem ... done! Size of subspace L: 8 Number of solutions: 2
# pretty-print and illustrate hlf
# label states (optional)
n_states = len(so.make_wavefunction_list( hlf_circuit ))
labels = ['']*n_states
labels[0] = '$\psi_0$'
labels[-2] = '$\psi_{ANS}$'
labels[-1] = '$\psi_M$'
so.pprint(hlf_circuit,'"Example: HLF 2D (3-qubit)"')
so.illustrate(hlf_circuit,labels,offset_ends=True)
#so.illustrate(hlf_circuit,offset_ends=False)
#plt.savefig('outputs/hlf2d_illustration')
"Example: HLF 2D (3-qubit)"
0: ──────H──────@──────S──────H──────M──────
│
1: ──────H──────┼─────────────H──────M──────
│
2: ──────H──────┼─────────────H──────M──────
│
3: ──────H──────@──────S──────H──────M──────
# print(so.highlight(hlf_circuit,'"HLF 2D"'))
Creates a test_state
out of two qubits. The state is a superposition, each in a different phase, to demonstrate visual represnting probability amplitudes and phases.
One of the contral notions in quantum computation is the notion that you are not computing with classical probability, which is a real number between zero and one. (Classically, an event can be said to occur with a chance between 0 and 100%.)
In quantum theory, the state of a system is described not be classical probabilies, but by complex amplitudes. Amplitudes have a magitude between zero (no chance) and one (certainty), but additionally have phase information, which is discarded in classical probability, but becomes an important tool in quantum computation.
Moreover, the gates in quantum computing operate on these complex amplitudes, rather than probabilities.
The classical probability is the square of the amplitude
Amplitudes are described by a magnitude between zero and one Like probabilies, amplitudes can have a magnitude between zero (no chance) and one (a certainty).
# would be cool to make a circuit to wind up with this state ...
test_state = np.array([1, 1j, -1, -1j])
test_state = so.normalize_state(test_state)
so.draw_wavefunction4(test_state, label='$\psi_{four\_phases}$' )
#so.pprint_circuit('', 'Two Qubit State Space (Same Probabilty, Different Phases)')
plt.show()