Selaa lähdekoodia

Added Measurement

Adam Kelly 5 vuotta sitten
vanhempi
commit
aa8e5ba7f0

+ 0 - 74
notebooks/In-Progress Experiments.ipynb

@@ -1,74 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "code",
-   "execution_count": 3,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "import qcgpu\n",
-    "\n",
-    "state = qcgpu.State(28)\n",
-    "\n",
-    "state.apply_all(qcgpu.gate.h())\n",
-    "\n",
-    "# state"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 4,
-   "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "1.0"
-      ]
-     },
-     "execution_count": 4,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "state.measure_qubit(0)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "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.15rc1"
-  }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}

+ 0 - 24
notebooks/ipython_cell_input.py

@@ -1,24 +0,0 @@
-def bench_qcgpu(n, depth):
-    state = qcgpu.State(n)
-
-    h = qcgpu.gate.h()
-    x = qcgpu.gate.x()
-    sqrt_x = qcgpu.gate.sqrt_x()
-
-    print('started')
-    start = time.time()
-
-    for level in range(depth):
-        for q in range(n):
-    
-            state.apply_gate(h, q)
-            state.apply_gate(sqrt_x, q)
-
-            if q != 0:
-                state.apply_controlled_gate(x, q, 0)
-        
-    runtime = time.time() - start
-    print('ended: ', runtime)
-    return runtime
-
-bench_qcgpu(26,5)

+ 0 - 16
notebooks/out.csv

@@ -1,16 +0,0 @@
-,num_qubits,depth,time
-0,2,10,0.2940499782562256
-1,2,20,0.2940499782562256
-2,2,30,0.2940499782562256
-3,3,10,0.2940499782562256
-4,3,20,0.2940499782562256
-5,3,30,0.2940499782562256
-6,4,10,0.2940499782562256
-7,4,20,0.2940499782562256
-8,4,30,0.2940499782562256
-9,5,10,0.2940499782562256
-10,5,20,0.2940499782562256
-11,5,30,0.2940499782562256
-12,6,10,0.2940499782562256
-13,6,20,0.2940499782562256
-14,6,30,0.2940499782562256

+ 0 - 89
notebooks/settings.json

@@ -1,89 +0,0 @@
-{
-    "control": {
-        "shadow": false, 
-        "size": 0.1
-    }, 
-    "gate_shadow": true, 
-    "gates": {
-        "AllocateQubitGate": {
-            "allocate_at_zero": false, 
-            "draw_id": false, 
-            "height": 0.15, 
-            "offset": 0.1, 
-            "pre_offset": 0.1, 
-            "width": 0.2
-        }, 
-        "DeallocateQubitGate": {
-            "height": 0.15, 
-            "offset": 0.2, 
-            "pre_offset": 0.1, 
-            "width": 0.2
-        }, 
-        "EntangleGate": {
-            "offset": 0.2, 
-            "pre_offset": 0.2, 
-            "width": 1.8
-        }, 
-        "HGate": {
-            "offset": 0.3, 
-            "pre_offset": 0.1, 
-            "width": 0.5
-        }, 
-        "MeasureGate": {
-            "height": 0.5, 
-            "offset": 0.2, 
-            "pre_offset": 0.2, 
-            "width": 0.75
-        }, 
-        "Ph": {
-            "height": 0.8, 
-            "offset": 0.3, 
-            "pre_offset": 0.2, 
-            "width": 1.0
-        }, 
-        "Rx": {
-            "height": 0.8, 
-            "offset": 0.3, 
-            "pre_offset": 0.2, 
-            "width": 1.0
-        }, 
-        "Ry": {
-            "height": 0.8, 
-            "offset": 0.3, 
-            "pre_offset": 0.2, 
-            "width": 1.0
-        }, 
-        "Rz": {
-            "height": 0.8, 
-            "offset": 0.3, 
-            "pre_offset": 0.2, 
-            "width": 1.0
-        }, 
-        "SqrtSwapGate": {
-            "height": 0.35, 
-            "offset": 0.1, 
-            "width": 0.35
-        }, 
-        "SqrtXGate": {
-            "offset": 0.3, 
-            "pre_offset": 0.1, 
-            "width": 0.7
-        }, 
-        "SwapGate": {
-            "height": 0.35, 
-            "offset": 0.1, 
-            "width": 0.35
-        }, 
-        "XGate": {
-            "height": 0.35, 
-            "offset": 0.1, 
-            "width": 0.35
-        }
-    }, 
-    "lines": {
-        "double_classical": true, 
-        "double_lines_sep": 0.04, 
-        "init_quantum": true, 
-        "style": "very thin"
-    }
-}

+ 52 - 7
qcgpu/backend.py

@@ -4,6 +4,8 @@ import numpy as np
 import pyopencl as cl
 import pyopencl.array as pycl_array
 from pyopencl.reduction import ReductionKernel
+from collections import defaultdict
+
 
 # Get the OpenCL kernel
 kernel_path = os.path.join(
@@ -34,7 +36,7 @@ class Backend:
 
         self.context = cl.create_some_context()
         self.queue = cl.CommandQueue(self.context)
-        self.program = cl.Program(self.context, kernel).build()
+        self.program = cl.Program(self.context, kernel).build(options="-cl-no-signed-zeros -cl-mad-enable -cl-fast-relaxed-math")
 
         # Buffer for the state vector
         self.buffer = pycl_array.to_device(
@@ -73,6 +75,26 @@ class Backend:
             self.dtype(gate.d)
         )
     
+    def measure(self, samples=1):
+        """Measure the state of a register"""
+        # This is a really horrible method that needs a rewrite - the memory
+        # is attrocious
+
+        probabilities = self.probabilities()
+
+        choices = np.random.choice(
+            np.arange(0, 2**self.num_qubits), 
+            samples, 
+            p=probabilities
+        )
+        
+        results = defaultdict(int)
+        for i in choices:
+            results[np.binary_repr(i, width=self.num_qubits)] += 1
+        
+        return dict(results)
+       
+
     def qubit_probability(self, target):
         """Get the probability of a single qubit begin measured as '0'"""
 
@@ -105,15 +127,38 @@ class Backend:
     def measure_qubit(self, target, samples):
         probability_of_0 = self.qubit_probability(target)
 
-        total = 0
+        
+
 
-        for i in range(samples):
-            outcome = 1 if random.random() > probability_of_0 else 0
-            total = total + outcome
-            
+        choices = np.random.choice(
+            [0, 1], 
+            samples, 
+            p=[probability_of_0, 1-probability_of_0]
+        )
+        
+        results = defaultdict(int)
+        for i in choices:
+            results[np.binary_repr(i, width=1)] += 1
         
-        return total
+        return dict(results)
+
+    def single_amplitude(self, i):
+        """Gets a single probability amplitude"""
+        out = pycl_array.to_device(
+            self.queue,
+            np.empty(1, dtype=np.complex64)
+        )
+
+        self.program.get_single_amplitude(
+            self.queue, 
+            (1, ), 
+            None, 
+            self.buffer.data,
+            out.data,
+            np.int32(i)
+        )
 
+        return out[0]
 
     def amplitudes(self):
         """Gets the probability amplitudes"""

+ 11 - 0
qcgpu/kernels/brute-force.cl

@@ -150,6 +150,17 @@ __kernel void apply_controlled_controlled_gate(
 
 
 /**
+ * Get a single amplitude
+ */
+__kernel void get_single_amplitude(
+    __global cfloat_t *const amplitudes,
+    __global cfloat_t *out,
+    int i)
+{
+    out[0] = amplitudes[i];
+}
+
+/**
  * Calculates The Probabilities Of A State Vector
  */
 __kernel void calculate_probabilities(

+ 3 - 0
qcgpu/state.py

@@ -41,6 +41,9 @@ class State:
     def measure_qubit(self, target, samples=1):
         return self.backend.measure_qubit(target, samples)
 
+    def measure(self, samples=1):
+        return self.backend.measure(samples)
+
     def amplitudes(self):
         return self.backend.amplitudes()