Skip to content

Commit

Permalink
Merge pull request #123 from rigetticomputing/bugfix/compiled-depende…
Browse files Browse the repository at this point in the history
…ncies

Made tomography requirements optional, documented their installation
  • Loading branch information
ntezak committed Dec 20, 2017
2 parents fa269a2 + 9170823 commit f974721
Show file tree
Hide file tree
Showing 16 changed files with 342 additions and 178 deletions.
44 changes: 34 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,8 @@ pip install -e .
This will install Grove’s dependencies if you do not already have them.
However, you will still need to install pyQuil and set up a connection to
the Rigetti Forest (see below).

Dependencies
------------

* NumPy
* SciPy
* NetworkX (for building and analyzing graphs)
* Matplotlib (useful for plotting)
* pytest (optional, for development testing)
* mock (optional, for development testing)
To enable the tomography module, you will also have to install qutip
and cvxpy, see below for more details.

Forest and pyQuil
-----------------
Expand All @@ -72,6 +64,38 @@ configured to run with a quantum virtual machine (QVM) or real quantum processor
See the pyQuil [docs](http://pyquil.readthedocs.io/en/latest/index.html) for
instructions on how to do this.

Installing the dependencies for Quantum Tomography
--------------------------------------------------

Quantum tomography relies on the external packages qutip and and cvxpy,
which can be somewhat tricky to install.

You can first attempt to just run
```
pip install -r requirements.txt
pip install -r optional-requirements.txt
pip install quantum-grove
```

If the installation of the optional requirements fails, you can manually
install the individual packages as

```
pip install cython==0.24.1 scs==1.2.6
pip install qutip==4.1 cvxpy
```
These are not the most recent versions but they are the only ones that
have consistently worked for us across different platforms and python
versions.

.. note::

For **Windows users**: Both qutip and cvxpy are fairly tricky to
install under windows and we therefore recommend using Anaconda's
``conda`` package manager to install these first and then ``pip``
to install ``quantum-grove``.


Building the Docs
-----------------

Expand Down
21 changes: 21 additions & 0 deletions docs/tomography.rst
Original file line number Diff line number Diff line change
Expand Up @@ -584,5 +584,26 @@ Run on the QPU & QVM, and calculate the fidelity
.. image:: _static/tomography/Tomography_13_1.png


Source Code Docs
----------------

.. automodule:: grove.tomography.tomography
:members:
:show-inheritance:

.. automodule:: grove.tomography.state_tomography
:members:
:show-inheritance:

.. automodule:: grove.tomography.process_tomography
:members:
:show-inheritance:

.. automodule:: grove.tomography.operator_utils
:members:
:show-inheritance:

.. automodule:: grove.tomography.utils
:members:
:show-inheritance:

70 changes: 40 additions & 30 deletions grove/tests/tomography/test_operator_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,90 +14,100 @@
# limitations under the License.
##############################################################################

import matplotlib
matplotlib.use('Agg')

import numpy as np
import pytest
from scipy.sparse import csr_matrix
import qutip as qt

import grove.tomography.utils as ut
import grove.tomography.operator_utils
from grove.tomography.operator_utils import to_realimag, FROBENIUS, is_projector, EPS, choi_matrix
from grove.tomography.utils import import_qutip, import_cvxpy

qt = import_qutip()
cvxpy = import_cvxpy()

if not qt:
pytest.skip("Qutip not installed, skipping tests", allow_module_level=True)

if not cvxpy:
pytest.skip("CVXPY not installed, skipping tests", allow_module_level=True)


def test_operator_basis():
assert ut.PAULI_BASIS.all_hermitian()
assert ut.PAULI_BASIS.is_orthonormal()
assert is_projector(ut.GS)
assert grove.tomography.operator_utils.PAULI_BASIS.all_hermitian()
assert grove.tomography.operator_utils.PAULI_BASIS.is_orthonormal()
assert is_projector(grove.tomography.operator_utils.GS)

two_qubit_pauli = ut.PAULI_BASIS.product(ut.PAULI_BASIS)
two_qubit_pauli = grove.tomography.operator_utils.PAULI_BASIS.product(
grove.tomography.operator_utils.PAULI_BASIS)
assert two_qubit_pauli.all_hermitian()
assert two_qubit_pauli.is_orthonormal()

sp = ut.PAULI_BASIS.super_basis()
sp = grove.tomography.operator_utils.PAULI_BASIS.super_basis()
assert sp.all_hermitian()
assert sp.is_orthonormal()

squared_pauli_basis = ut.PAULI_BASIS ** 2
squared_pauli_basis = grove.tomography.operator_utils.PAULI_BASIS ** 2
for (l1, o1), (l2, o2) in zip(two_qubit_pauli, squared_pauli_basis):
assert l1 == l2
assert (o1 - o2).norm(FROBENIUS) < EPS

assert np.allclose(ut.PAULI_BASIS.basis_transform.T.toarray() * np.sqrt(2),
np.array([[1., 0, 0, 1], [0, 1, 1, 0], [0, 1j, -1j, 0], [1, 0, 0, -1]]))
assert np.allclose(
grove.tomography.operator_utils.PAULI_BASIS.basis_transform.T.toarray() * np.sqrt(2),
np.array([[1., 0, 0, 1], [0, 1, 1, 0], [0, 1j, -1j, 0], [1, 0, 0, -1]]))

sX = qt.to_super(ut.QX)
tmX = ut.PAULI_BASIS.transfer_matrix(sX).toarray()
sX = qt.to_super(grove.tomography.operator_utils.QX)
tmX = grove.tomography.operator_utils.PAULI_BASIS.transfer_matrix(sX).toarray()
assert np.allclose(tmX, np.diag([1, 1, -1, -1]))
assert (sX - ut.PAULI_BASIS.super_from_tm(tmX)).norm(FROBENIUS) < EPS
assert (sX - grove.tomography.operator_utils.PAULI_BASIS.super_from_tm(tmX)).norm(FROBENIUS) < EPS

pb3 = ut.PAULI_BASIS**3
pb3 = grove.tomography.operator_utils.PAULI_BASIS ** 3
assert pb3.dim == 4**3
assert pb3 == ut.n_qubit_pauli_basis(3)
assert pb3 == grove.tomography.operator_utils.n_qubit_pauli_basis(3)

assert ut.PAULI_BASIS**1 == ut.PAULI_BASIS
assert grove.tomography.operator_utils.PAULI_BASIS ** 1 == grove.tomography.operator_utils.PAULI_BASIS

assert np.allclose(ut.PAULI_BASIS.project_op(ut.GS).toarray().ravel(),
np.array([1, 0, 0, 1])/np.sqrt(2))
assert np.allclose(grove.tomography.operator_utils.PAULI_BASIS.project_op(
grove.tomography.operator_utils.GS).toarray().ravel(),
np.array([1, 0, 0, 1]) / np.sqrt(2))

assert str(ut.PAULI_BASIS) == "<span[I,X,Y,Z]>"
assert str(grove.tomography.operator_utils.PAULI_BASIS) == "<span[I,X,Y,Z]>"


def test_super_operator_tools():
X, Y, Z, I = ut.QX, ut.QY, ut.QZ, ut.QI
X, Y, Z, I = grove.tomography.operator_utils.QX, grove.tomography.operator_utils.QY, grove.tomography.operator_utils.QZ, grove.tomography.operator_utils.QI
bs = (I, X, Y, Z)

Xs = qt.sprepost(X, X)
# verify that Y+XYX==0 ( or XYX==-Y)
assert (Y + Xs(Y)).norm(FROBENIUS) < EPS

ptmX = np.array([[(bj * Xs(bk)).tr().real / 2 for bk in bs] for bj in bs])
assert np.allclose(ptmX, ut.PAULI_BASIS.transfer_matrix(Xs).toarray())
assert np.allclose(ptmX, grove.tomography.operator_utils.PAULI_BASIS.transfer_matrix(Xs).toarray())

xchoi = qt.super_to_choi(Xs)
my_xchoi = choi_matrix(ptmX, ut.PAULI_BASIS)
my_xchoi = choi_matrix(ptmX, grove.tomography.operator_utils.PAULI_BASIS)
assert (my_xchoi - xchoi).norm(FROBENIUS) < EPS

ys = qt.sprepost(Y, Y)
ptm_y = np.array([[(bj * ys(bk)).tr().real / 2 for bk in bs] for bj in bs])
assert np.allclose(ptm_y, ut.PAULI_BASIS.transfer_matrix(ys).toarray())
assert np.allclose(ptm_y, grove.tomography.operator_utils.PAULI_BASIS.transfer_matrix(ys).toarray())

ychoi = qt.super_to_choi(ys)
my_ychoi = choi_matrix(ptm_y, ut.PAULI_BASIS)
my_ychoi = choi_matrix(ptm_y, grove.tomography.operator_utils.PAULI_BASIS)
assert (my_ychoi - ychoi).norm(FROBENIUS) < EPS

y2 = (-.25j * np.pi * Y).expm()
y2s = qt.sprepost(y2, y2.dag())
ptm_y2 = np.array([[(bj * y2s(bk)).tr().real / 2 for bk in bs] for bj in bs])
assert np.allclose(ptm_y2, ut.PAULI_BASIS.transfer_matrix(y2s).toarray())
assert np.allclose(ptm_y2, grove.tomography.operator_utils.PAULI_BASIS.transfer_matrix(y2s).toarray())

y2choi = qt.super_to_choi(y2s)
my_y2choi = choi_matrix(ptm_y2, ut.PAULI_BASIS)
my_y2choi = choi_matrix(ptm_y2, grove.tomography.operator_utils.PAULI_BASIS)
assert (my_y2choi - y2choi).norm(FROBENIUS) < EPS


def test_to_realimag():
op = ut.QX + ut.QY
op = grove.tomography.operator_utils.QX + grove.tomography.operator_utils.QY
res = to_realimag(op)
assert isinstance(res, csr_matrix)
rd = res.toarray()
Expand Down
17 changes: 12 additions & 5 deletions grove/tests/tomography/test_process_tomography.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,11 @@
##############################################################################

import matplotlib
matplotlib.use('Agg')
import pytest
import os
import numpy as np
from mock import patch
from mock import MagicMock, Mock
import qutip as qt
import json

from pyquil.api import QVMConnection
Expand All @@ -33,11 +31,20 @@
do_process_tomography, ProcessTomography,
COMPLETELY_POSITIVE)
from grove.tomography.process_tomography import (TRACE_PRESERVING)
from grove.tomography.utils import (POVM_PI_BASIS, make_histogram,
from grove.tomography.utils import (make_histogram,
sample_bad_readout, basis_state_preps,
estimate_assignment_probs, BAD_2Q_READOUT, SEED,
EPS, CNOT_PROGRAM)
from grove.tomography.operator_utils import make_diagonal_povm
EPS, CNOT_PROGRAM, import_qutip, import_cvxpy)
from grove.tomography.operator_utils import make_diagonal_povm, POVM_PI_BASIS

qt = import_qutip()
cvxpy = import_cvxpy()

if not qt:
pytest.skip("Qutip not installed, skipping tests", allow_module_level=True)

if not cvxpy:
pytest.skip("CVXPY not installed, skipping tests", allow_module_level=True)


SHOTS_PATH = os.path.join(os.path.dirname(__file__), 'process_shots.json')
Expand Down
34 changes: 22 additions & 12 deletions grove/tests/tomography/test_state_tomography.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,40 @@
# limitations under the License.
##############################################################################

import matplotlib
matplotlib.use('Agg')
import pytest
import json
import os

import numpy as np
from mock import patch
import pytest

from mock import MagicMock
import qutip as qt
import json
from mock import patch
from pyquil.api import QVMConnection

from grove.tomography.tomography import (MAX_QUBITS_STATE_TOMO,
default_channel_ops)
from grove.tomography.operator_utils import make_diagonal_povm
from grove.tomography.process_tomography import (TRACE_PRESERVING)
from grove.tomography.state_tomography import (DEFAULT_STATE_TOMO_SETTINGS,
state_tomography_programs,
do_state_tomography, StateTomography,
UNIT_TRACE,
POSITIVE)
from grove.tomography.process_tomography import (TRACE_PRESERVING)
from grove.tomography.utils import (POVM_PI_BASIS, make_histogram,
from grove.tomography.tomography import (MAX_QUBITS_STATE_TOMO,
default_channel_ops)
from grove.tomography.utils import (make_histogram,
sample_bad_readout, basis_state_preps,
estimate_assignment_probs, BELL_STATE_PROGRAM,
BAD_2Q_READOUT, EPS, SEED)
from grove.tomography.operator_utils import make_diagonal_povm
BAD_2Q_READOUT, EPS, SEED, import_qutip, import_cvxpy)
from grove.tomography.operator_utils import POVM_PI_BASIS

qt = import_qutip()
cvxpy = import_cvxpy()

if not qt:
pytest.skip("Qutip not installed, skipping tests", allow_module_level=True)

if not cvxpy:
pytest.skip("CVXPY not installed, skipping tests", allow_module_level=True)


SHOTS_PATH = os.path.join(os.path.dirname(__file__), 'state_shots.json')
RESULTS_PATH = os.path.join(os.path.dirname(__file__), 'state_results.json')
Expand Down
15 changes: 11 additions & 4 deletions grove/tests/tomography/test_tomography.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
##############################################################################

import matplotlib
import pytest

import grove.tomography.utils

matplotlib.use('Agg')
from grove.tomography.tomography import _SDP_SOLVER
from grove.tomography.utils import notebook_mode
import grove.tomography.tomography as tomography


qt = grove.tomography.utils.import_qutip()
cvxpy = grove.tomography.utils.import_cvxpy()

if not qt:
pytest.skip("Qutip not installed, skipping tests", allow_module_level=True)

if not cvxpy:
pytest.skip("CVXPY not installed, skipping tests", allow_module_level=True)


def test_SDP_SOLVER():
Expand Down

0 comments on commit f974721

Please sign in to comment.