Browse Source

Added tests

Adam Kelly 5 years ago
parent
commit
d25767118d
6 changed files with 51 additions and 168 deletions
  1. 0 91
      example.py
  2. 10 8
      qcgpu/gate.py
  3. 0 69
      requirements.txt
  4. 5 0
      setup.cfg
  5. 2 0
      setup.py
  6. 34 0
      tests/test_gate.py

+ 0 - 91
example.py

@@ -1,91 +0,0 @@
-from __future__ import print_function
-import qcgpu
-
-s = qcgpu.State(3)
-h = qcgpu.gate.h()
-
-print(h)
-
-s.apply_gate(h, 0)
-
-print(s)
-
-# from __future__ import absolute_import
-# from __future__ import print_function
-# import pyopencl as cl
-# import pyopencl.array as cl_array
-# import numpy
-# import numpy.linalg as la
-
-# a = numpy.random.rand(8).astype(numpy.complex64)
-
-# ctx = cl.create_some_context()
-# queue = cl.CommandQueue(ctx)
-
-# a_dev = cl_array.to_device(queue, a)
-
-# prg = cl.Program(ctx, """
-#     #include <pyopencl-complex.h>
-
-#     /*
-#     * Returns the nth number where a given digit
-#     * is cleared in the binary representation of the number
-#     */
-#     static int nth_cleared(int n, int target)
-#     {
-#         int mask = (1 << target) - 1;
-#         int not_mask = ~mask;
-
-#         return (n & mask) | ((n & not_mask) << 1);
-#     }
-
-#     /*
-#     * Applies a single qubit gate to the register.
-#     * The gate matrix must be given in the form:
-#     *
-#     *  A B
-#     *  C D
-#     */
-#     __kernel void apply_gate(
-#         __global cfloat_t *amplitudes,
-#         int target,
-#         cfloat_t A,
-#         cfloat_t B,
-#         cfloat_t C,
-#         cfloat_t D)
-#     {
-#         int const global_id = get_global_id(0);
-
-#         int const zero_state = nth_cleared(global_id, target);
-
-#         // int const zero_state = state & (~(1 << target)); // Could just be state
-#         int const one_state = zero_state | (1 << target);
-
-#         cfloat_t const zero_amp = amplitudes[zero_state];
-#         cfloat_t const one_amp = amplitudes[one_state];
-
-#         amplitudes[zero_state] = cfloat_add(cfloat_mul(A, zero_amp), cfloat_mul(B, one_amp));
-#         amplitudes[one_state] = cfloat_add(cfloat_mul(D, one_amp), cfloat_mul(C, zero_amp));
-#     }
-
-#     __kernel void sum(__global cfloat_t *a, cfloat_t b)
-#     {
-#       int gid = get_global_id(0);
-#       a[gid] = cfloat_add(a[gid], b);
-#     }
-#     """).build()
-
-# # kernel = prg.sum
-# # kernel.set_scalar_arg_dtypes([
-# #     None,
-# #     None,
-# #     numpy.complex64
-# # ])
-
-# prg.sum(queue, (int(a.shape[0] / 2),), None, a_dev.data, numpy.complex64(3+2j))
-
-# prg.sum(queue, (2, ), None, a_dev.data, numpy.complex64(3+2j))
-
-# print(a_dev)
-
-# print((a.shape[0] / 2,))

+ 10 - 8
qcgpu/gate.py

@@ -2,6 +2,8 @@ import numpy as np
 
 class Gate:
     def __init__(self, gate):
+        gate = np.array(gate)
+        
         if gate.shape != (2, 2):
             raise ValueError(
                 "Gate is not a 2x2 matrix. " + 
@@ -10,7 +12,7 @@ class Gate:
             )
 
         # Check the gate is unitary
-        if (not np.allclose(np.eye(gate.shape[0]), gate.H * gate)):
+        if (not np.allclose(np.eye(gate.shape[0]), np.dot(gate.conjugate().transpose(), gate))):
             raise ValueError("gate is not unitary.")
 
         self.a = complex(gate[0, 0])
@@ -22,22 +24,22 @@ class Gate:
         return '[{:.4f}, {:.4f}]\n[{:.4f}, {:.4f}]'.format(self.a, self.b, self.c, self.d)
 
 def h():
-    return Gate(np.matrix([[1, 1], [1, -1]]) / np.sqrt(2))
+    return Gate(np.array([[1, 1], [1, -1]]) / np.sqrt(2))
 
 def x():
-    return Gate(np.matrix([[0, 1], [1, 0]]))
+    return Gate(np.array([[0, 1], [1, 0]]))
 
 def y():
-    return Gate(np.matrix([[0, -1j], [1j, 0]]))
+    return Gate(np.array([[0, -1j], [1j, 0]]))
 
 def z():
-    return Gate(np.matrix([[1, 0], [0, -1]]))
+    return Gate(np.array([[1, 0], [0, -1]]))
 
 def s():
-    return Gate(np.matrix([[1, 0], [0, 1j]]))
+    return Gate(np.array([[1, 0], [0, 1j]]))
 
 def t():
-    return Gate(np.matrix([[1, 0], [0, np.exp(np.pi * 1j / 4)]]))
+    return Gate(np.array([[1, 0], [0, np.exp(np.pi * 1j / 4)]]))
 
 def sqrt_x():
-    return Gate(0.5 * np.matrix([[1+1j, 1-1j], [1-1j, 1+1j]]))
+    return Gate(0.5 * np.array([[1+1j, 1-1j], [1-1j, 1+1j]]))

+ 0 - 69
requirements.txt

@@ -1,69 +0,0 @@
-appdirs==1.4.3
-apturl==0.5.2
-asn1crypto==0.24.0
-Brlapi==0.6.6
-certifi==2018.1.18
-chardet==3.0.4
-chrome-gnome-shell==0.0.0
-colour==0.1.5
-command-not-found==0.3
-cryptography==2.1.4
-cupshelpers==1.0
-decorator==4.3.0
-defer==1.0.6
-distro-info==0.18
-httplib2==0.9.2
-idna==2.6
-keyring==10.6.0
-keyrings.alt==3.0
-language-selector==0.1
-launchpadlib==1.10.6
-lazr.restfulclient==0.13.5
-lazr.uri==1.0.3
-louis==3.5.0
-macaroonbakery==1.1.3
-Mako==1.0.7
-MarkupSafe==1.0
-mpmath==1.0.0
-numpy==1.15.2
-oauth==1.0.1
-olefile==0.45.1
-opencv-python==3.4.2.17
-pexpect==4.2.1
-Pillow==5.2.0
-progressbar==2.5
-protobuf==3.0.0
-pycairo==1.17.1
-pycrypto==2.6.1
-pycups==1.9.73
-pygobject==3.26.1
-pymacaroons==0.13.0
-PyNaCl==1.1.2
-pyopencl==2018.2
-pyRFC3339==1.0
-python-apt==1.6.2
-python-debian==0.1.32
-pytools==2018.5.2
-pytz==2018.3
-pyxdg==0.25
-PyYAML==3.12
--e git+https://github.com/QCGPU/qcgpu-rust@745ea6d5c1f23d08a20d300a68e5a40d03e3b063#egg=qcgpu
-reportlab==3.4.0
-requests==2.18.4
-requests-unixsocket==0.1.5
-scipy==1.1.0
-screen-resolution-extra==0.0.0
-SecretStorage==2.3.1
-simplejson==3.13.2
-six==1.11.0
-system-service==0.3
-systemd-python==234
-tqdm==4.24.0
-ubuntu-drivers-common==0.0.0
-ufw==0.35
-unattended-upgrades==0.1
-urllib3==1.22
-usb-creator==0.3.3
-wadllib==1.3.2
-xkit==0.0.0
-zope.interface==4.3.2

+ 5 - 0
setup.cfg

@@ -0,0 +1,5 @@
+[aliases]
+test=pytest
+
+[tool:pytest]
+addopts = --verbose

+ 2 - 0
setup.py

@@ -18,4 +18,6 @@ setuptools.setup(
         "License :: OSI Approved :: MIT License",
         "Operating System :: OS Independent",
     ],
+    setup_requires=['pytest-runner', 'pyopencl', 'pybind11', 'numpy'],
+    tests_require=["pytest"]
 )

+ 34 - 0
tests/test_gate.py

@@ -0,0 +1,34 @@
+import pytest
+from qcgpu.gate import Gate, h, x, y, z, s, t, sqrt_x
+import numpy as np
+
+def test_gate_creation():
+    Gate(np.array([[0, 1], [1, 0]])) # A clearly unitary gate
+    h()
+    x()
+    y()
+    z()
+    s()
+    t()
+    sqrt_x()
+
+def test_using_list():
+    return Gate([[1, 0], [0, 1]])
+
+def test_non_unitary_gate_creation_fails():
+    # A clearly non unitary gate
+    with pytest.raises(Exception):
+        return Gate(np.array([[12, 33], [-7j, 1]]))
+
+def test_large_gate_creation_fails():
+    # A gate that is not 2x2
+    with pytest.raises(Exception):
+        return Gate(np.ones(4))
+
+def test_using_scalar_fails():
+    with pytest.raises(Exception):
+        return Gate(2)
+
+def test_using_string_fails():
+    with pytest.raises(Exception):
+        return Gate("this should fail")