Skip to content

Commit

Permalink
Merge pull request #87 from rigetticomputing/IpynbExamples
Browse files Browse the repository at this point in the history
Ipynb examples
  • Loading branch information
jotterbach committed Oct 11, 2017
2 parents 5084356 + e2c2a0e commit c9c8713
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 2 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,6 @@ ENV/

# Pycharm
.idea/

# converted Ipynb files
examples/*.py
14 changes: 14 additions & 0 deletions demo_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash -e


pushd ./examples
echo "cleaning old compiled notebooks"
rm -f *.py

echo "Converting notebooks"
jupyter nbconvert --to script *.ipynb

echo "Running notebooks"
python *.py

popd
164 changes: 164 additions & 0 deletions examples/SimonsAlgorithm.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This Notebook is a brief sketch of how to use Simon's algorithm.\n",
"We start by declaring all necessary imports."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from collections import defaultdict\n",
"from pyquil.api import SyncConnection\n",
"import numpy as np\n",
"from mock import patch\n",
"\n",
"from grove.simon.simon import Simon, create_valid_2to1_bitmap"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Simon's algorithm can be used to find the mask $m$ of a 2-to-1 periodic Boolean function defined by\n",
"$$f(x) = f(x \\oplus m)$$\n",
"where $\\oplus$ is the bit-wise XOR operator. To create one we can define a mask as a string and call a utility to generate a map. To assert the correct result we check it against an expected map"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"mask = '110'\n",
"bm = create_valid_2to1_bitmap(mask, random_seed=42)\n",
"expected_map = {\n",
" '000': '001',\n",
" '001': '101',\n",
" '010': '000',\n",
" '011': '111',\n",
" '100': '000',\n",
" '101': '111',\n",
" '110': '001',\n",
" '111': '101'\n",
"}\n",
"for k, v in bm.items():\n",
" assert v == expected_map[k]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To understand what a 2-to-1 function is let us revert the map and collect all keys tha point to the same value. As the assertion shows all values have 2 distinct origins"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"reverse_bitmap = defaultdict(list)\n",
"for k, v in bm.items():\n",
" reverse_bitmap[v].append(k)\n",
"\n",
"expected_reverse_bitmap = {\n",
" '001': ['000', '110'],\n",
" '101': ['001', '111'],\n",
" '000': ['010', '100'],\n",
" '111': ['011', '101']\n",
"}\n",
"\n",
"for k, v in reverse_bitmap.items():\n",
" assert sorted(v) == sorted(expected_reverse_bitmap[k])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To use Simon's algorithm on a Quantum Hardware we need to define the connection to the QVM or QPU. However we don't have a real connection in this notebook, so we just mock out the response. If you run this notebook, ensure to replace `cxn` with a pyQuil connection object."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"with patch(\"pyquil.api.SyncConnection\") as cxn:\n",
" # Need to mock multiple returns as an iterable\n",
" cxn.run_and_measure.side_effect = [\n",
" (np.asarray([0, 1, 1], dtype=int), ),\n",
" (np.asarray([1, 1, 1], dtype=int), ),\n",
" (np.asarray([1, 1, 1], dtype=int), ),\n",
" (np.asarray([1, 0, 0], dtype=int), ),\n",
" ]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now let's run Simon's algorithm. We instantiate the Simon object and then call its `find_mask` mehtod with the connection object and the 2-to-1 function whose mask we wish to find.\n",
"Finally we assert its correctness by checking with the mask we used to generate the function"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"sa = Simon()\n",
"found_mask = sa.find_mask(cxn, bm)\n",
"assert ''.join([str(b) for b in found_mask]) == mask, \"Found mask is not expected mask\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If the assertion succeeded we know we found the mask and we got our result."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
6 changes: 4 additions & 2 deletions grove/simon/simon.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,16 @@ def create_valid_2to1_bitmap(mask, random_seed=None):
:return: dictionary containing the truth table of a valid 2-to-1 boolean function
:rtype: Dict[String, String]
"""
if random_seed:
if random_seed is not None:
rd.seed(random_seed)
bit_map = create_1to1_bitmap(mask)
n_samples = int(len(bit_map.keys()) / 2)

# We create a 2-to-1 mapping and hence need to generate a list with exactly half the possible
# bit-strings. We do this by randomly sampling the set of all possible bit-strings.
range_of_2to1_map = list(rd.choice(list(bit_map.keys()), replace=False, size=n_samples))
# Moreover we sort the keys as the return order is not guaranteed and we want to remove
# this randomness
range_of_2to1_map = list(rd.choice(list(sorted(bit_map.keys())), replace=False, size=n_samples))

list_of_bitstring_tuples = sorted([(k, v) for k, v in bit_map.items()], key=lambda x: x[0])

Expand Down
4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ matplotlib
funcsigs
six

# demos
jupyter
jupyter_contrib_nbextensions

# test dependencies
tox
pytest >= 3.0.0
Expand Down
4 changes: 4 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ setenv =
deps=
-rrequirements.txt
commands=
; unit tests
py.test --cov=grove
; check docs build correctly
sphinx-build -b html docs/ docs/_build
; test example notebooks work
./demo_tests.sh


0 comments on commit c9c8713

Please sign in to comment.