Explorar o código

Started stripping down repository

Adam Kelly %!s(int64=5) %!d(string=hai) anos
pai
achega
8e3158d156

+ 0 - 41
.travis.yml

@@ -1,41 +0,0 @@
-language: generic
-os: osx
-
-# language: python
-# python:
-#   - "2.7.15"
-#   - "3.6.6"
-#   - "3.7-dev"
-
-# dist: trusty
-
-# addons:
-#   apt:
-#     packages:
-#       - opencl-headers
-#       - ocl-icd-opencl-dev
-#       - fglrx
-
-git:
-  depth: false
-
-install:
-    # There is sometimes issues with the install order so do this bad boi first
-  - pip3 install pybind11
-  - pip3 install -r requirements.txt
-  - pip3 install -e .
-
-script:
-  - python3 setup.py test
-
-after_success:
-  - make html
-
-deploy:
-  provider: pages
-  skip-cleanup: true
-  github-token: $GITHUB_TOKEN  # Set in travis-ci.org dashboard, marked secure
-  keep-history: true
-  local-dir: ./build/html
-  on:
-    branch: master

+ 1 - 1
LICENSE

@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2018 Adam Kelly
+Copyright (c) 2019 Adam Kelly
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal

+ 0 - 19
Makefile

@@ -1,19 +0,0 @@
-# Minimal makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS    =
-SPHINXBUILD   = sphinx-build
-SOURCEDIR     = docs
-BUILDDIR      = build
-
-# Put it first so that "make" without argument is like "make help".
-help:
-	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
-
-.PHONY: help Makefile
-
-# Catch-all target: route all unknown targets to Sphinx using the new
-# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
-%: Makefile
-	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

+ 7 - 20
README.md

@@ -1,33 +1,20 @@
-# QCGPU
+# Tangle 
 
-[![Travis
-(.org)](https://img.shields.io/travis/QCGPU/qcgpu.svg?style=for-the-badge)](https://travis-ci.org/QCGPU/qcgpu)
-[![PyPi
-Version](https://img.shields.io/pypi/v/qcgpu.svg?style=for-the-badge)](https://pypi.python.org/pypi/qcgpu)
 [![License](https://img.shields.io/pypi/l/qcgpu.svg?style=for-the-badge)](https://pypi.python.org/pypi/qcgpu/)
 [![GitHub
 stars](https://img.shields.io/github/stars/qcgpu/qcgpu.svg?style=for-the-badge&label=Stars)](https://github.com/QCGPU/qcgpu)
 [![Unitary Fund](https://img.shields.io/badge/Supported%20By-UNITARY%20FUND-brightgreen.svg?style=for-the-badge)](http://unitary.fund)
 
-Open Source, High Performance & Hardware Accelerated, Quantum Computer
-Simulator. Read the [research paper](https://arxiv.org/abs/1805.00988).
+Open Source, High Performance & Hardware Accelerated, Tools for Quantum Computation
+Simulator. 
 
 **Features:**
 
-  - Written with OpenCL. Accelerated your simulations with GPUs and other
-    accelerators, while still running cross device and cross platform.
-  - Simulation of arbitrary quantum circuits
-  - Includes example algorithm implementations
-  - Support for arbitrary gate creation/application, with many built in.
+* It's cool
+* GPU, MPI and Stuff
 
 ## Installing
 
-This library is distributed on
-[PyPI](https://pypi.python.org/pypi/qcgpu) and can be installed using
-pip:
+not quite sure yet on this one.
 
-```bash
-$ pip install qcgpu
-```
-
-For more information read the full [installing docs](https://qcgpu.github.io/qcgpu/install.html).
+For more information read the full [installing docs](https://qcgpu.github.io/qcgpu/install.html). 

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 146
benchmark/Visualize.ipynb


+ 0 - 159
benchmark/benchmark.py

@@ -1,159 +0,0 @@
-import click
-import time
-import random
-import statistics
-import csv
-import os.path
-import math
-
-from qiskit import ClassicalRegister, QuantumRegister, QuantumCircuit
-from qiskit.wrapper import load_qasm_file
-from qiskit import QISKitError, execute, Aer
-
-from projectq import MainEngine
-import projectq.ops as ops
-from projectq.backends import Simulator
-
-import qcgpu
-
-# Implementation of the Quantum Fourier Transform
-def construct_circuit(num_qubits):
-    q = QuantumRegister(num_qubits)
-    circ = QuantumCircuit(q)
-
-    # Quantum Fourier Transform
-    for j in range(num_qubits):
-        for k in range(j):
-            circ.cu1(math.pi/float(2**(j-k)), q[j], q[k])
-        circ.h(q[j])
-
-    return circ
-
-
-# Benchmarking functions
-qiskit_backend = Aer.get_backend('statevector_simulator')
-eng = MainEngine(backend=Simulator(), engine_list=[])
-
-# Setup the OpenCL Device
-qcgpu.backend.create_context()
-
-def bench_qiskit(qc):
-    start = time.time()
-    job_sim = execute(qc, qiskit_backend)
-    sim_result = job_sim.result()
-    return time.time() - start
-
-def bench_qcgpu(num_qubits):
-    start = time.time()
-    state = qcgpu.State(num_qubits)
-
-    for j in range(num_qubits):
-        for k in range(j):
-            state.cu1(j, k, math.pi/float(2**(j-k)))
-        state.h(j)
-
-    state.backend.queue.finish()
-    return time.time() - start
-
-def bench_projectq(num_qubits):
-    start = time.time()
-
-    q = eng.allocate_qureg(num_qubits)
-
-    for j in range(num_qubits):
-        for k in range(j):
-            ops.CRz(math.pi / float(2**(j-k))) | (q[j], q[k])
-    ops.H | q[j]
-    eng.flush()
-
-    t = time.time() - start
-    # measure to get rid of runtime error message
-    for j in q:
-        ops.Measure | j
-
-    return t
-    
-
-# Reporting
-def create_csv(filename):
-    file_exists = os.path.isfile(filename)
-    csvfile = open(filename, 'a')
-   
-    headers = ['name', 'num_qubits', 'time']
-    writer = csv.DictWriter(csvfile, delimiter=',', lineterminator='\n',fieldnames=headers)
-
-    if not file_exists:
-        writer.writeheader()  # file doesn't exist yet, write a header
-
-    return writer
-
-def write_csv(writer, data):
-    writer.writerow(data)
-
-
-
-@click.command()
-@click.option('--samples', default=5, help='Number of samples to take for each qubit.')
-@click.option('--qubits', default=5, help='How many qubits you want to test for')
-@click.option('--out', default='benchmark_data.csv', help='Where to store the CSV output of each test')
-@click.option('--single', default=False, help='Only run the benchmark for a single amount of qubits, and print an analysis')
-def benchmark(samples, qubits, out, single):
-    if single:
-        # functions = bench_qcgpu, bench_qiskit, bench_projectq
-        functions = bench_projectq, 
-        times = {f.__name__: [] for f in functions}
-
-        names = []
-        means = []
-
-        qc = construct_circuit(qubits)
-        # Run the benchmarks
-        for i in range(samples):
-            progress = (i) / (samples)
-            if samples > 1:
-                print("\rProgress: [{0:50s}] {1:.1f}%".format('#' * int(progress * 50), progress*100), end="", flush=True)
-
-            func = random.choice(functions)
-            if func.__name__ != 'bench_qiskit':
-                t = func(qubits)
-            else:
-                t = func(qc)
-            times[func.__name__].append(t)
-
-        print('')
-
-        for name, numbers in times.items():
-            print('FUNCTION:', name, 'Used', len(numbers), 'times')
-            print('\tMEDIAN', statistics.median(numbers))
-            print('\tMEAN  ', statistics.mean(numbers))
-            if len(numbers) > 1:
-                print('\tSTDEV ', statistics.stdev(numbers))
-
-        return
-
-    
-
-    functions = bench_qcgpu, bench_qiskit, bench_projectq
-    # times = {f.__name__: [] for f in functions}
-    writer = create_csv(out)
-
-    for n in range(23, qubits):
-        # Progress counter
-        progress = (n+1) / (qubits)
-        print("\rProgress: [{0:50s}] {1:.1f}%".format('#' * int(progress * 50), progress*100), end="", flush=True)
-
-        # Construct the circuit
-        qc = construct_circuit(n+1)
-
-        # Run the benchmarks
-        for i in range(samples):
-            func = random.choice(functions)
-            if func.__name__ != 'bench_qiskit':
-                t = func(n + 1)
-            else:
-                t = func(qc)
-            # times[func.__name__].append(t)
-            write_csv(writer, {'name': func.__name__, 'num_qubits': n+1, 'time': t})
-
-if __name__ == '__main__':
-    benchmark()

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 2315
benchmark/benchmark_data.csv


+ 0 - 9
docs/_templates/util/footer.html

@@ -1,9 +0,0 @@
-<script type="text/x-mathjax-config">
-    MathJax.Hub.Config({
-      tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']], displayMath: [['$$', '$$'], ['\\[', '\\]']]}
-    });
-    </script>
-
-<script type="text/javascript"
-   src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
-</script>

+ 0 - 187
docs/conf.py

@@ -1,187 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Configuration file for the Sphinx documentation builder.
-#
-# This file does only contain a selection of the most common options. For a
-# full list see the documentation:
-# http://www.sphinx-doc.org/en/master/config
-
-# -- Path setup --------------------------------------------------------------
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-#
-import os
-import sys
-sys.path.insert(0, os.path.abspath('../'))
-
-
-# -- Project information -----------------------------------------------------
-
-project = u'QCGPU'
-copyright = u'2018, Adam Kelly'
-author = u'Adam Kelly'
-
-# The short X.Y version
-version = u''
-# The full version, including alpha/beta/rc tags
-release = u'0.1.0'
-
-
-# -- General configuration ---------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-#
-# needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be
-# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
-# ones.
-extensions = [
-    'sphinx.ext.autodoc',
-    'sphinx.ext.intersphinx',
-    'sphinx.ext.mathjax',
-    'sphinx.ext.ifconfig',
-    'sphinx.ext.githubpages',
-    'sphinx.ext.napoleon'
-]
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
-
-# The suffix(es) of source filenames.
-# You can specify multiple suffix as a list of string:
-#
-# source_suffix = ['.rst', '.md']
-source_suffix = '.rst'
-
-# The master toctree document.
-master_doc = 'index'
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#
-# This is also used if you do content translation via gettext catalogs.
-# Usually you set "language" from the command line for these cases.
-language = None
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-# This pattern also affects html_static_path and html_extra_path.
-exclude_patterns = []
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = None
-
-
-# -- Options for HTML output -------------------------------------------------
-
-# The theme to use for HTML and HTML Help pages.  See the documentation for
-# a list of builtin themes.
-#
-html_theme = 'press'
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further.  For a list of options available for each theme, see the
-# documentation.
-#
-# html_theme_options = {}
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-# html_static_path = ['_static']
-
-# Custom sidebar templates, must be a dictionary that maps document names
-# to template names.
-#
-# The default sidebars (for documents that don't match any pattern) are
-# defined by theme itself.  Builtin themes are using these templates by
-# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
-# 'searchbox.html']``.
-#
-# html_sidebars = {}
-
-
-# -- Options for HTMLHelp output ---------------------------------------------
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'QCGPUdoc'
-
-
-# -- Options for LaTeX output ------------------------------------------------
-
-latex_elements = {
-    # The paper size ('letterpaper' or 'a4paper').
-    #
-    # 'papersize': 'letterpaper',
-
-    # The font size ('10pt', '11pt' or '12pt').
-    #
-    # 'pointsize': '10pt',
-
-    # Additional stuff for the LaTeX preamble.
-    #
-    # 'preamble': '',
-
-    # Latex figure (float) alignment
-    #
-    # 'figure_align': 'htbp',
-}
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title,
-#  author, documentclass [howto, manual, or own class]).
-latex_documents = [
-    (master_doc, 'QCGPU.tex', u'QCGPU Documentation',
-     u'Adam Kelly', 'manual'),
-]
-
-
-# -- Options for manual page output ------------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
-    (master_doc, 'qcgpu', u'QCGPU Documentation',
-     [author], 1)
-]
-
-
-# -- Options for Texinfo output ----------------------------------------------
-
-# Grouping the document tree into Texinfo files. List of tuples
-# (source start file, target name, title, author,
-#  dir menu entry, description, category)
-texinfo_documents = [
-    (master_doc, 'QCGPU', u'QCGPU Documentation',
-     author, 'QCGPU', 'One line description of project.',
-     'Miscellaneous'),
-]
-
-
-# -- Options for Epub output -------------------------------------------------
-
-# Bibliographic Dublin Core info.
-epub_title = project
-
-# The unique identifier of the text. This can be a ISBN number
-# or the project homepage.
-#
-# epub_identifier = ''
-
-# A unique identification for the text.
-#
-# epub_uid = ''
-
-# A list of files that should not be packed into the epub file.
-epub_exclude_files = ['search.html']
-
-
-# -- Extension configuration -------------------------------------------------
-
-# -- Options for intersphinx extension ---------------------------------------
-
-# Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {'https://docs.python.org/': None}

+ 0 - 108
docs/gates.rst

@@ -1,108 +0,0 @@
-Quantum Gates
-=============
-
-In quantum computing, gates are used to manipulate quantum registers and
-to implement quantum algorithms.
-
-Built-In Gates
---------------
-
-There are a number of gates built into QCGPU. They can all be applied
-the same way:
-
-.. code:: python
-
-   import qcgpu
-
-   register = qcgpu.State(2)
-
-   state.h(0) # Applies the Hadamard (H) gate to the first qubit.
-   state.x(1) # Applies a pauli-x (NOT) gate to the second qubit.
-
-``h`` and ``x`` can be replaced with any of the following:
-
--  The Hadamard gate: **h** - ``state.h(0)``
--  The S gate: **s** - ``state.s(0)``
--  The T gate: **t** - ``state.t(0)``
--  The Pauli-X / NOT gate: **x** - ``state.x(0)``
--  The Pauli-Y gate: **y** - ``state.y(0)``
--  The Pauli-Z gate: **z** - ``state.z(0)``
--  The CNOT gate: **cx** -
-   ``state.cx(0, 1) # CNOT with control = 0, target = 1``
--  The SWAP gate: **swap** -
-   ``state.swap(0,1) # Swaps the 0th and 1st qubit``
--  The Toffoli gate: **toffoli** -
-   ``state.toffoli(0, 1, 2) # Toffoli with controls = (0, 1), target = 2``
-
-These are all shorthand methods for the application of arbitrary gates.
-For example, the application of a Hadamard gate above is shorthand for
-
-.. code:: python
-
-   import qcgpu
-
-   h = qcgpu.gate.h()
-
-   register = qcgpu.State(5)
-   register.apply_gate(h, 0)
-
-You can also use any of the gates as controlled gates. For example, the
-application of the CNOT gate above is shorthand for
-
-.. code:: python
-
-   import qcgpu
-
-   x = qcgpu.gate.x()
-
-   register = qcgpu.State(5)
-   register.apply_controlled_gate(x, 0, 1)
-
-Applying A Gate To A Whole Register
-----------------------------------
-
-There is a convenience method to apply a gate to every qubit in the register.
-The following applies a Hadamard gate to the whole register,
-
-.. code:: python
-
-   import qcgpu
-
-   h = qcgpu.gate.h()
-
-   register = qcgpu.State(5)
-   register.apply_all(h)
-   
-
-User Defined Gates
-------------------
-
-Gates in QCGPU are represented by the ``qcgpu.Gate`` class.
-
-The only gates that can be defined by the user are single qubit gates.
-
-The process of creating a gate is
-
-.. code:: python
-
-   import qcgpu
-   import numpy as np
-
-   gate_matrix = np.array([
-       [1, 0],
-       [0, np.exp(1j * np.pi / 4)]
-   ])
-
-   gate = qcgpu.Gate(gate_matrix)
-
-The input to the ``Gate`` constructor is checked to be a 2x2 unitary
-matrix.
-
-This newly created gate can then be applied the long hand way,
-
-.. code:: python
-
-   import qcgpu 
-
-   register = qcgpu.State(2)
-   register.apply_gate(gate, 0)

+ 0 - 13
docs/guide.rst

@@ -1,13 +0,0 @@
-==========
-User Guide
-==========
-
-This section covers the full usage of QCGPU.
-It will also contain some information about what each part represents.
-
-.. toctree::
-   :maxdepth: 2
-   
-   registers
-   gates
-   operations

+ 0 - 43
docs/index.rst

@@ -1,43 +0,0 @@
-=====
-QCGPU
-=====
-
-.. image:: https://img.shields.io/travis/QCGPU/qcgpu.svg?style=for-the-badge   
-   :alt: Travis (.org)   
-   :target: https://travis-ci.org/QCGPU/qcgpu
-.. image:: https://img.shields.io/pypi/v/qcgpu.svg?style=for-the-badge
-   :target: https://pypi.python.org/pypi/qcgpu
-   :alt: PyPi Version
-.. image:: https://img.shields.io/pypi/l/qcgpu.svg?style=for-the-badge
-   :target: https://pypi.python.org/pypi/qcgpu/
-   :alt: License
-.. image:: https://img.shields.io/github/stars/qcgpu/qcgpu.svg?style=for-the-badge&label=Stars
-   :alt: GitHub stars
-   :target: https://github.com/QCGPU/qcgpu
-
-QCGPU is an open source, high performance library for simulating
-quantum circuits. 
-It takes advantage of hardware acceleration with
-OpenCL.
-Read the `research paper`_.
-
-.. _`research paper`: https://arxiv.org/abs/1805.00988
-
-
-Table of Contents
-==================
-
-.. toctree::
-   :maxdepth: 3
-   
-   install
-   quickstart
-   guide
-   
-
-.. Python Modules
-    ==============
-    .. autosummary::
-        :nosignatures:
-        qcgpu
-    :ref:`modindex`

+ 0 - 46
docs/install.rst

@@ -1,46 +0,0 @@
-============
-Installation
-============
-
-Prerequisites
--------------
-
-To use QCGPU you will need to be using `Python 2.7 or later <https://www.python.org/downloads/>`_.
-You will also need to ensure that you have an `OpenCL <https://www.khronos.org/opencl/>`_ implementation installed. 
-This is done by default on MacOS, but you shuld check that ``clinfo`` or some other diagnostic command will run.
-
-You can also use `Anaconda 3 <https://www.continuum.io/downloads>`_, which will have many of the required dependencies already installed.
-
-Installing from PyPI
---------------------
-
-This library is distributed on `PyPI <https://pypi.python.org/pypi/qcgpu>`_ and can be installed using pip:
-
-.. code:: sh
-
-   $ pip install qcgpu
-
-If you run into any issues, you should try installing from source.
-
-Installing from Source
-----------------------
-
-You can install QCGPU from the source. First, clone the repository off
-GitHub:
-
-.. code:: sh
-
-   $ git clone https://github.com/qcgpu/qcgpu
-
-Then you will need to ``cd`` into the directory, and install the
-requirements.
-
-.. code:: sh
-
-   $ pip install -r requirements.txt
-
-And finally you can install:
-
-.. code:: sh
-
-   $ python setup.py install

+ 0 - 70
docs/operations.rst

@@ -1,70 +0,0 @@
-Quantum Operations
-==================
-
-There are a number of operations you can perform on quantum registers
-with QCGPU.
-
-Measurement
------------
-
-Measurement of a register in QCGPU doesn’t collapse the state (although
-this may be added in the future). When you measure the state, you can
-specify the number of times to sample. The output of this ``measure``
-function is a dictionary with the bitstrings of the outputs, along with
-the number of times they were measured.
-
-You can measure a register as follows,
-
-.. code:: python
-
-   import qcgpu
-
-   register = qcgpu.State(5)
-
-   register.measure(samples=1000)
-   # {'00000': 1000}
-
-There is also a convenience method to measure only a single qubit.
-Again, the state is not collapsed
-
-.. code:: python
-
-   import qcgpu
-
-   register = qcgpu.State(5)
-
-   register.h(0)
-
-   register.measure_qubit(0, samples=1000)
-   # {'1': 523, '0': 477}
-
-Probability
------------
-
-QCGPU provides another method for getting the probability of each
-outcome.
-
-The probability of getting an outcome :math:`j` from a state
-:math:`\lvert \psi \rangle = \sum_{j = 0}^{2^n - 1} \alpha_j \lvert j \rangle`
-is
-
-.. math::
-
-
-   P(j) = \lvert \alpha_j \lvert^2
-
-The method ``probabilities`` returns a numpy array with each of the
-values corresponding to :math:`\lvert \alpha_j \lvert ^2` for each index
-:math:`j`.
-
-.. code:: python
-
-   import qcgpu
-
-   register = qcgpu.State(1)
-   register.h(0)
-
-   register.probabilities() # [0.5, 0.5]
-
-This method is particularly useful to plot the probabilities of each
-outcome.

+ 0 - 42
docs/quickstart.rst

@@ -1,42 +0,0 @@
-===============
-Getting Started
-===============
-
-When using this library, you will most likely be using the :class:`~qiskit.State` class.
-This class represents the state of a quantum register. 
-Using this class you can apply gates to the register, measure, get the state vector and things like that.
-
-To run a simple quantum circuit, you can use something like this,
-
-.. code-block:: python
-
-    # Import QCGPU
-    import qcgpu
-
-    # Create a new quantum register with 2 qubits
-    register = qcgpu.State(2)
-
-    # Apply a hadamard (H) gate to the first qubit.
-    # You should note that the qubits are zero indexed
-    register.h(0)
-
-    # Add a controlled not (CNOT/CX) gate, with the control as
-    # the first qubit and target as the second.
-    # The register will now be in the bell state.
-    register.cx(0, 1)
-
-    # Perform a measurement with 1000 samples
-    results = register.measure(samples=1000)
-
-    # Show the results
-    print(results)
-
-The output of a measurement gives a dictionary of measurement outcomes,
-along with how often they occurred.
-
-.. code-block:: python
-
-    {'00': 486, '11': 514}
-
-There are a few different ways to do things using QCGPU, 
-so you should check out the rest of the documentation too

+ 0 - 49
docs/registers.rst

@@ -1,49 +0,0 @@
-=================
-Quantum Registers
-=================
-
-QCGPU provides a class to represent the register, ``qcgpu.State``. The
-register class stores (on the OpenCL device) a state vector. This state
-vector is a chunk of memory, the size of which is:
-
-.. math::
-
-
-   64 \cdot 2^n \text{ bits}.
-
-This means you would need just 2kb of memory to have a 5 qubit register,
-a 30 qubit register would take up 9gb of memory.
-
-This is something to be aware of, as the state vector must fit in the
-memory of the device you wish to use.
-
-Using the ``State`` class
--------------------------
-
-To create a new register, you can use
-
-.. code:: python
-
-   import qcgpu
-
-   register = qcgpu.State(5)
-
-This will create a 5 qubit register.
-
-When you run this, you may be prompted to choose a device. This is
-normal, as you can have more than 1 device that supports OpenCL in your
-computer. Just choose the one you want.
-
-Mathematical Description
--------------------------
-
-This class represents a state vector :math:`\lvert \psi \rangle` with
-
-.. math::
-
-
-   \lvert \psi \rangle = \sum_{j = 0}^{2^n - 1} \alpha_j \lvert j \rangle
-
-where :math:`n` is the number of qubits, :math:`\alpha_j` is the
-amplitude and the state is :math:`j` runs overall :math:`2^n` basis
-states.

+ 0 - 27
examples/bell_state.py

@@ -1,27 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-Bell State / EPR Pair
-=====================
-
-The Bell State, also known as the EPR pair (after Einstein, Podosky and Rosen)
-is the simplest example of entanglement.
-
-The Bell State is defined as the maximally entangled quantum state of two qubits.
-"""
-
-def bell_state():
-    import qcgpu
-
-    print("Creating Bell State")
-
-    state = qcgpu.State(2)
-
-    state.h(0)
-    state.cx(0, 1)
-
-    print("Measurement Results:")
-    print(state.measure(samples = 1000))
-
-if __name__== "__main__":
-  bell_state()

+ 0 - 54
examples/bernstein_vazirani.py

@@ -1,54 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-Bernstein-Vazirani Algorithm
-============================
-
-This algorithm finds a hidden integer :math:`a \in \{ 0, 1\}^n` from
-an oracle :math:`f_a` which returns a bit :math:`a \cdot x \equiv \sum_i a_i x_i \mod 2`
-for an input :math:`x \in \{0,1\}^n`.
-
-A classical oracle returns :math:`f_a(x) = a \dot x \mod 2`, while the quantum oracle
-must be queried with superpositions of input :math:`x`'s.
-
-To solve this problem classically, the hidden integer can be found by checking the
-oracle with the inputs :math:`x = 1,2,\dots,2^i,2^{n-1}`, where each
-query reveals the :math:`i`th bit of :math:`a` (:math:`a_i`).
-This is the optimal classical solution, and is :math:`O(n)`. Using a quantum oracle and the
-Bernstein-Vazirani algorithm, :math:`a` can be found with just one query to the oracle.
-
-The Algorithm
--------------
-
-1. Initialize :math:`n` qubits in the state :math:`\lvert 0, \dots, 0\rangle`.
-2. Apply the Hadamard gate :math:`H` to each qubit.
-3. Apply the inner product oracle.
-4. Apply the Hadamard gate :math:`H` to each qubit.
-5. Measure the register
-
-From this procedure, we find that the registers measured value is equal to that of
-the original hidden integer.
-"""
-
-def bernstein_vazirani():
-    import qcgpu
-
-    num_qubits = 7 # The number of qubits to use
-    a = 101 # The hidden integer, bitstring is 1100101
-
-    register = qcgpu.State(num_qubits) # Create a new quantum register
-
-    register.apply_all(qcgpu.gate.h()) # Apply a hadamard gate to each qubit
-
-    # Apply the inner products oracle
-    for i in range(num_qubits):
-        if a & (1 << i) != 0:
-            register.z(i)
-
-    register.apply_all(qcgpu.gate.h()) # Apply a hadamard gate to each qubit
-
-    results = register.measure(samples=1000) # Measure the register (sample 1000 times)
-    print(results)
-
-if __name__== "__main__":
-  bernstein_vazirani()

+ 0 - 41
examples/deutsch-jozsa.py

@@ -1,41 +0,0 @@
-import qcgpu
-
-# 3 qubits, f(x) = x_0 NOT x_1 x_2
-# Balanced
-balanced_state = qcgpu.State(3)
-
-balanced_state.apply_all(qcgpu.gate.h())
-
-# Oracle U_f
-balanced_state.h(2)
-balanced_state.z(0)
-balanced_state.cx(1, 2)
-balanced_state.h(2)
-
-balanced_state.apply_all(qcgpu.gate.h())
-
-outcomes = balanced_state.measure(samples = 1000)
-
-if int(max(outcomes, key=outcomes.get)) == 0:
-    print('constant')
-else:
-    print('balanced')
-
-
-# 3 qubits, f(x) = 0
-# Constant
-constant_state = qcgpu.State(3)
-
-constant_state.apply_all(qcgpu.gate.h())
-
-# Oracle is equivalent to the identity gate, 
-# thus has no effect on the state
-
-constant_state.apply_all(qcgpu.gate.h())
-
-outcomes = constant_state.measure(samples = 1000)
-
-if int(max(outcomes, key=outcomes.get)) == 0:
-    print('constant')
-else:
-    print('balanced')

+ 0 - 22
examples/qft.py

@@ -1,22 +0,0 @@
-"""
-QFT
-=====================
-
-This is an implementation of the quantum Fourier transform.
-"""
-
-import qcgpu
-import math
-
-def qft():
-    print('start')
-    state = qcgpu.State(24)
-    num_qubits = state.num_qubits
-
-    for j in range(num_qubits):
-        for k in range(j):
-            state.cu1(j, k, math.pi/float(2**(j-k)))
-        state.h(j)
-
-if __name__== "__main__":
-    qft()

+ 0 - 35
make.bat

@@ -1,35 +0,0 @@
-@ECHO OFF
-
-pushd %~dp0
-
-REM Command file for Sphinx documentation
-
-if "%SPHINXBUILD%" == "" (
-	set SPHINXBUILD=sphinx-build
-)
-set SOURCEDIR=docs
-set BUILDDIR=build
-
-if "%1" == "" goto help
-
-%SPHINXBUILD% >NUL 2>NUL
-if errorlevel 9009 (
-	echo.
-	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
-	echo.installed, then set the SPHINXBUILD environment variable to point
-	echo.to the full path of the 'sphinx-build' executable. Alternatively you
-	echo.may add the Sphinx directory to PATH.
-	echo.
-	echo.If you don't have Sphinx installed, grab it from
-	echo.http://sphinx-doc.org/
-	exit /b 1
-)
-
-%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
-goto end
-
-:help
-%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
-
-:end
-popd

+ 0 - 7
qcgpu/__init__.py

@@ -1,7 +0,0 @@
-"""
-QCGPU Base module
-"""
-
-import qcgpu.gate
-from qcgpu.state import State
-from qcgpu.gate import Gate

+ 0 - 467
qcgpu/backend.py

@@ -1,467 +0,0 @@
-import os
-import random
-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 = """
-#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);
-}
-
-///////////////////////////////////////////////
-// KERNELS
-///////////////////////////////////////////////
-
-/*
- * 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));
-}
-
-/*
- * Applies a controlled single qubit gate to the register.
- */
-__kernel void apply_controlled_gate(
-    __global cfloat_t *amplitudes,
-    int control,
-    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 one_state = zero_state | (1 << target); // Set the target bit
-
-    int const control_val_zero = (((1 << control) & zero_state) > 0) ? 1 : 0;
-    int const control_val_one = (((1 << control) & one_state) > 0) ? 1 : 0;
-
-    cfloat_t const zero_amp = amplitudes[zero_state];
-    cfloat_t const one_amp = amplitudes[one_state];
-
-    if (control_val_zero == 1)
-    {
-        amplitudes[zero_state] = cfloat_add(cfloat_mul(A, zero_amp), cfloat_mul(B, one_amp));
-    }
-
-    if (control_val_one == 1)
-    {
-        amplitudes[one_state] = cfloat_add(cfloat_mul(D, one_amp), cfloat_mul(C, zero_amp));
-    }
-}
-
-/*
- * Applies a controlled-controlled single qubit gate to the register.
- */
-__kernel void apply_controlled_controlled_gate(
-    __global cfloat_t *amplitudes,
-    int control,
-    int control_2,
-    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 one_state = zero_state | (1 << target); // Set the target bit
-
-    int const control_val_zero = (((1 << control) & zero_state) > 0) ? 1 : 0;
-    int const control_val_one = (((1 << control) & one_state) > 0) ? 1 : 0;
-    int const control_val_two_zero = (((1 << control_2) & zero_state) > 0) ? 1 : 0;
-    int const control_val_two_one = (((1 << control_2) & one_state) > 0) ? 1 : 0;
-
-    cfloat_t const zero_amp = amplitudes[zero_state];
-    cfloat_t const one_amp = amplitudes[one_state];
-
-    if (control_val_zero == 1 && control_val_two_zero == 1)
-    {
-        amplitudes[zero_state] = cfloat_add(cfloat_mul(A, zero_amp), cfloat_mul(B, one_amp));
-    }
-
-    if (control_val_one == 1 && control_val_two_one == 1)
-    {
-        amplitudes[one_state] = cfloat_add(cfloat_mul(D, one_amp), cfloat_mul(C, zero_amp));
-    }
-}
-
-/*
- * Swaps the states of two qubits in the register
- * NOT MIGRATED
- */
-// __kernel void swap(
-//     __global cfloat_t *const amplitudes,
-//     __global cfloat_t *amps,
-//     int first_qubit,
-//     int second_qubit)
-// {
-//     int const state = get_global_id(0);
-
-//     int const first_bit_mask = 1 << first_qubit;
-//     int const second_bit_mask = 1 << second_qubit;
-
-//     int const new_second_bit = ((state & first_bit_mask) >> first_qubit) << second_qubit;
-//     int const new_first_bit = ((state & second_bit_mask) >> second_qubit) << first_qubit;
-
-//     int const new_state = (state & !first_bit_mask & !second_bit_mask) | new_first_bit | new_second_bit;
-
-//     amps[new_state] = amplitudes[state];
-// }
-
-
-/**
- * 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(
-    __global cfloat_t *const amplitudes,
-    __global float *probabilities)
-{
-    int const state = get_global_id(0);
-    cfloat_t amp = amplitudes[state];
-
-    probabilities[state] = cfloat_abs(cfloat_mul(amp, amp));
-}
-
-/**
- * Initializes a register to the value 1|0..100...0>
- *                                          ^ target
- */
-__kernel void initialize_register(
-    __global cfloat_t *amplitudes,
-    int const target)
-{
-    int const state = get_global_id(0);
-    if (state == target)
-    {
-        amplitudes[state] = cfloat_new(1, 0);
-    }
-    else
-    {
-        amplitudes[state] = cfloat_new(0, 0);
-    }
-}
-
-/**
- * Collapses a qubit in the register
- */
-__kernel void collapse(
-    __global cfloat_t *amplitudes, 
-    int const target,
-    int const outcome, 
-    float const norm)
-{
-    int const state = get_global_id(0);
-
-    if (((state >> target) & 1) == outcome) {
-        amplitudes[state] = cfloat_mul(amplitudes[state], cfloat_new(norm, 0.0));
-    }
-    else
-    {
-        amplitudes[state] = cfloat_new(0.0, 0.0);
-    }
-}
-"""
-
-# Setup the OpenCL Context here to not prompt every execution
-context = None
-program = None
-
-
-class Backend:
-    """
-    A class for the OpenCL backend to the simulator.
-
-    This class shouldn't be used directly, as many of the
-    methods don't have the same input checking as the State
-    class.
-    """
-
-    # @profile
-    def __init__(self, num_qubits, dtype=np.complex64):
-        if not context:
-            create_context()
-        
-        """
-        Initialize a new OpenCL Backend
-
-        Takes an argument of the number of qubits to use
-        in the register, and returns the backend.
-        """
-        self.num_qubits = num_qubits
-        self.dtype = dtype
-
-        self.queue = cl.CommandQueue(context)
-
-        # Buffer for the state vector
-        self.buffer = pycl_array.to_device(
-            self.queue,
-            np.eye(1, 2**num_qubits, dtype=dtype)
-        )
-
-    def apply_gate(self, gate, target):
-        """Applies a gate to the quantum register"""
-        program.apply_gate(
-            self.queue,
-            [int(2**self.num_qubits / 2)],
-            None,
-            self.buffer.data,
-            np.int32(target),
-            self.dtype(gate.a),
-            self.dtype(gate.b),
-            self.dtype(gate.c),
-            self.dtype(gate.d)
-        )
-
-    def apply_controlled_gate(self, gate, control, target):
-        """Applies a controlled gate to the quantum register"""
-
-        program.apply_controlled_gate(
-            self.queue,
-            [int(2**self.num_qubits / 2)],
-            None,
-            self.buffer.data,
-            np.int32(control),
-            np.int32(target),
-            self.dtype(gate.a),
-            self.dtype(gate.b),
-            self.dtype(gate.c),
-            self.dtype(gate.d)
-        )
-    
-    def apply_controlled_controlled_gate(self, gate, control1, control2, target):
-        """Applies a controlled controlled gate (such as a toffoli gate) to the quantum register"""
-
-        program.apply_controlled_controlled_gate(
-            self.queue,
-            [int(2**self.num_qubits / 2)],
-            None,
-            self.buffer.data,
-            np.int32(control1),
-            np.int32(control2),
-            np.int32(target),
-            self.dtype(gate.a),
-            self.dtype(gate.b),
-            self.dtype(gate.c),
-            self.dtype(gate.d)
-        )
-
-    def seed(self, val):
-        random.seed(val)
-        
-    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()
-        # print(probabilities)
-        # print(np.sum(self.amplitudes()))
-        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 measure_first(self, num, samples):
-        probabilities = self.probabilities()
-        # print(probabilities)
-        # print(np.sum(self.amplitudes()))
-        choices = np.random.choice(
-            np.arange(0, 2**self.num_qubits), 
-            samples, 
-            p=probabilities
-        )
-        
-        results = defaultdict(int)
-        for i in choices:
-            key = np.binary_repr(i, width=self.num_qubits)[-num:]
-            results[key] += 1
-        
-        return dict(results)
-       
-
-    def qubit_probability(self, target):
-        """Get the probability of a single qubit begin measured as '0'"""
-
-        preamble = """
-        #include <pyopencl-complex.h>
-
-        float probability(int target, int i, cfloat_t amp) {
-            if ((i & (1 << target )) != 0) {
-                return 0;
-            }
-            // return 6.0;
-            float abs = cfloat_abs(amp);
-            return abs * abs;
-        }
-        """
-        
-
-        kernel = ReductionKernel(
-            context, 
-            np.float, 
-            neutral = "0",
-            reduce_expr="a + b",
-            map_expr="probability(target, i, amps[i])",
-            arguments="__global cfloat_t *amps, __global int target",
-            preamble=preamble
-        )
-
-        return kernel(self.buffer, target).get()
-        
-    def reset(self, target):
-        probability_of_0 = self.qubit_probability(target)
-        norm = 1 / np.sqrt(probability_of_0)
-        
-        program.collapse(
-            self.queue,
-            [int(2**self.num_qubits)],
-            # 2**self.num_qubits,
-            None,
-            self.buffer.data,
-            np.int32(target),
-            np.int32(0),
-            np.float32(norm)
-        )
-
-    def measure_collapse(self, target):
-        probability_of_0 = self.qubit_probability(target)
-        random_number = random.random()
-
-        if random_number <= probability_of_0:
-            outcome = '0'
-            norm = 1 / np.sqrt(probability_of_0)
-        else:
-            outcome = '1'
-            norm = 1 / np.sqrt(1 - probability_of_0)
-
-        program.collapse(
-            self.queue,
-            [int(2**self.num_qubits)],
-            # 2**self.num_qubits,
-            None,
-            self.buffer.data,
-            np.int32(target),
-            np.int32(outcome),
-            np.float32(norm)
-        )
-        return outcome
-
-    def measure_qubit(self, target, samples):
-        probability_of_0 = self.qubit_probability(target)
-
-        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 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)
-        )
-
-        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"""
-        return self.buffer.get()
-    
-    def probabilities(self):
-        """Gets the squared absolute value of each of the amplitudes"""
-        out = pycl_array.to_device(
-            self.queue,
-            np.zeros(2**self.num_qubits, dtype=np.float32)
-        )
-
-        program.calculate_probabilities(
-            self.queue,
-            out.shape,
-            None,
-            self.buffer.data,
-            out.data
-        )
-
-        return out.get()
-        
-    def release(self):
-        self.buffer.base_data.release()
-    
-def create_context():
-    global context
-    global program
-    context = cl.create_some_context()
-    program = cl.Program(context, kernel).build(options="-cl-no-signed-zeros -cl-mad-enable -cl-fast-relaxed-math")

+ 0 - 67
qcgpu/gate.py

@@ -1,67 +0,0 @@
-import numpy as np
-import functools
-
-def memoize(func):
-    cache = func.cache = {}
-
-    @functools.wraps(func)
-    def memoized_func():
-        key = 'a'
-        if key not in cache:
-            cache[key] = func()
-        return cache[key]
-
-    return memoized_func
-
-class Gate:
-    def __init__(self, gate, unitary=True):
-        gate = np.array(gate)
-        
-        if gate.shape != (2, 2):
-            raise ValueError(
-                "Gate is not a 2x2 matrix. " + 
-                "For larger gates, please decompose into 2x2 matrices " +
-                "and/or use the controlled gate functionality."
-            )
-
-        # Check the gate is unitary
-        if unitary:
-            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])
-        self.b = complex(gate[0, 1])
-        self.c = complex(gate[1, 0])
-        self.d = complex(gate[1, 1])
-
-    def __repr__(self):
-        return '[{:.4f}, {:.4f}]\n[{:.4f}, {:.4f}]'.format(self.a, self.b, self.c, self.d)
-
-@memoize
-def h():
-    return Gate(np.array([[1, 1], [1, -1]]) / np.sqrt(2))
-
-@memoize
-def x():
-    return Gate(np.array([[0, 1], [1, 0]]))
-
-@memoize
-def y():
-    return Gate(np.array([[0, -1j], [1j, 0]]))
-
-@memoize
-def z():
-    return Gate(np.array([[1, 0], [0, -1]]))
-
-@memoize
-def s():
-    return Gate(np.array([[1, 0], [0, 1j]]))
-
-@memoize
-def t():
-    return Gate(np.array([[1, 0], [0, np.exp(np.pi * 1j / 4)]]))
-
-@memoize
-def sqrt_x():
-    return Gate(0.5 * np.array([[1+1j, 1-1j], [1-1j, 1+1j]]))
-

+ 0 - 204
qcgpu/state.py

@@ -1,204 +0,0 @@
-"""
-Quantum Register Object
-"""
-import qcgpu
-from qcgpu.backend import Backend
-import pyopencl as cl
-import numpy as np
-
-class State:
-    """A class for representing quantum registers.
-
-    The State class is the QCGPU representation of a quantum 
-    register / state vector.
-
-    This class is what should be used to perform the simulations,
-    and has method for things such as applying gates, measurements,
-    getting probabilities and such.
-
-    As QCGPU uses OpenCL, you may be queried about which OpenCL device
-    to use. This will only happen when running things such a python repl,
-    or running a script using QCGPU from the command line. Otherwise, a
-    device will be chosen heuristically.
-
-    When the register is created, it will be left in the state
-
-    .. math::
-
-        \\lvert 000 \\dots 0 \\rangle
-
-    With the given number of qubits.
-
-    Args:
-        num_qubits (int): The number of qubits to create in the register.  
-            This must be greater then zero.
-
-    Returns:
-        State: A representation of the quantum register.
-
-    Examples
-        >>> qcgpu.State(3)
-            Choose platform:
-            [0] <pyopencl.Platform 'NVIDIA CUDA' at 0x2f22390>
-            Choice [0]:0
-            Set the environment variable PYOPENCL_CTX='0' to avoid being asked again.
-            [[array(1.+0.j, dtype=complex64)]
-             [array(0.+0.j, dtype=complex64)]
-             [array(0.+0.j, dtype=complex64)]
-             [array(0.+0.j, dtype=complex64)]]
-    """
-    def __init__(self, num_qubits):
-        
-        if not isinstance(num_qubits, int):
-            raise ValueError("num_qubits must be an int")
-        if num_qubits <= 0:
-            raise ValueError("num_qubits must be a positive integer")
-
-        #: The number of qubits that are in the register
-        self.num_qubits = num_qubits
-        self.backend = Backend(num_qubits)
-
-    def apply_gate(self, gate, target):
-        """Applies a single qubit unitary gate to the register.
-
-        Args:
-            gate (~qcgpu.Gate): The gate to be applied to the register
-            target (int): The index of the qubit in the register that the gate
-                is to be applied to.
-        """
-        if not isinstance(target, int) or target < 0:
-            print(target)
-            raise ValueError("target must be an int >= 0")
-
-        # TODO: Check that gate is correct
-
-        self.backend.apply_gate(gate, target)
-
-    def apply_all(self, gate):
-        # TODO: Check that gate is correct
-        for i in range(self.num_qubits):
-            self.apply_gate(gate, i)
-
-    def apply_controlled_gate(self, gate, control, target):
-        if not isinstance(target, int) or target < 0:
-            raise ValueError("target must be an int >= 0")
-        
-        if not isinstance(control, int) or control < 0:
-            raise ValueError("control must be an int >= 0")
-
-        # TODO: Check that gate is correct
-
-        self.backend.apply_controlled_gate(gate, control, target)
-    
-    def apply_controlled_controlled_gate(self, gate, control, control2, target):
-        if not isinstance(target, int) or target < 0:
-            raise ValueError("target must be an int >= 0")
-        
-        if not isinstance(control, int) or control < 0:
-            raise ValueError("control must be an int >= 0")
-
-        if not isinstance(control2, int) or control2 < 0:
-            raise ValueError("control must be an int >= 0")
-
-        # TODO: Check that gate is correct
-
-        self.backend.apply_controlled_controlled_gate(gate, control, control2, target)
-
-    def measure_qubit(self, target, samples=1):
-        return self.backend.measure_qubit(target, samples)
-
-    def measure_collapse(self, target):
-        return self.backend.measure_collapse(target)
-
-    def measure(self, samples=1):
-        return self.backend.measure(samples)
-
-    def measure_first(self, num=1, samples=1):
-        return self.backend.measure_first(num, samples)
-
-    def amplitudes(self):
-        return self.backend.amplitudes()[0]
-    
-    def probabilities(self):
-        return self.backend.probabilities()[0]
-
-    def __repr__(self):
-        """A string representation of the state"""
-
-        # TODO: Finish this method
-        return np.array_str(self.backend.buffer)
-
-
-    # Gates
-    def h(self, target):
-        self.apply_gate(qcgpu.gate.h(), target)
-
-    def x(self, target):
-        self.apply_gate(qcgpu.gate.x(), target)
-
-    def y(self, target):
-        self.apply_gate(qcgpu.gate.y(), target)
-
-    def z(self, target):
-        self.apply_gate(qcgpu.gate.z(), target)
-
-    def s(self, target):
-        self.apply_gate(qcgpu.gate.s(), target)
-
-    def t(self, target):
-        self.apply_gate(qcgpu.gate.t(), target)
-
-    def sqrt_x(self, target):
-        self.apply_gate(qcgpu.gate.sqrt_x(), target)
-
-    def cx(self, control, target):
-        self.apply_controlled_gate(qcgpu.gate.x(), control, target)
-
-    def cnot(self, control, target):
-        self.apply_controlled_gate(qcgpu.gate.x(), control, target)
-
-    def toffoli(self, control, control2, target):
-        self.apply_controlled_controlled_gate(qcgpu.gate.x(), control, control2, target)
-
-    def u(self, target, theta, phi, lda):
-        a = np.exp(-1j * (phi + lda) / 2) * np.cos(theta / 2)
-        b = - np.exp(-1j * (phi - lda) / 2) * np.sin(theta / 2)
-        c = np.exp(1j * (phi - lda) / 2) * np.sin(theta / 2)    
-        d = np.exp(1j * (phi + lda) / 2) * np.cos(theta / 2)
-    
-        gate_matrix = np.array([
-            [a, b],
-            [c, d]
-        ])
-        self.apply_gate(qcgpu.Gate(gate_matrix), target)
-    
-    def u1(self, target, lda):
-        self.u(target, 0, 0, lda)
-
-    def u2(self, target, phi, lda):
-        self.u(target, np.pi / 2, phi, lda)
-
-    def u3(self, target, theta, phi, lda):
-        self.u(target, theta, phi, lda)
-
-    def cu(self, control, target, theta, phi, lda):
-        a = np.exp(-1j * (phi + lda) / 2) * np.cos(theta / 2)
-        b = - np.exp(-1j * (phi - lda) / 2) * np.sin(theta / 2)
-        c = np.exp(1j * (phi - lda) / 2) * np.sin(theta / 2)    
-        d = np.exp(1j * (phi + lda) / 2) * np.cos(theta / 2)
-    
-        gate_matrix = np.array([
-            [a, b],
-            [c, d]
-        ])
-        self.apply_controlled_gate(qcgpu.Gate(gate_matrix), control, target)
-
-
-    def cu1(self, control, target, lda):
-        self.cu(control, target, 0, 0, lda)
-
-    def cu2(self, control, target, phi, lda):
-        self.cu(control, target, np.pi / 2, phi, lda)
-
-    def cu3(self, control, target, theta, phi, lda):
-        self.cu(control, target, theta, phi, lda)

+ 0 - 7
requirements.txt

@@ -1,7 +0,0 @@
-Mako==1.0.7
-numpy==1.15.2
-pybind11==2.2.4
-pyopencl==2018.2
-scipy==1.1.0
-Sphinx==1.8.1
-sphinx-press-theme

+ 0 - 5
setup.cfg

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

+ 0 - 24
setup.py

@@ -1,24 +0,0 @@
-import setuptools
-
-with open("README.md", "r") as fh:
-    long_description = fh.read()
-
-setuptools.setup(
-    name="qcgpu",
-    version="0.0.4",
-    author="Adam Kelly",
-    author_email="adamkelly2201@gmail.com",
-    description="An OpenCL based quantum computer simulator",
-    long_description=long_description,
-    long_description_content_type="text/markdown",
-    url="https://github.com/qcgpu/qcgpu",
-    packages=setuptools.find_packages(),
-    classifiers=[
-        "Programming Language :: Python :: 3",
-        "License :: OSI Approved :: MIT License",
-        "Operating System :: OS Independent",
-    ],
-    setup_requires=['pytest-runner'],
-    install_requires=['mako', 'pyopencl', 'pybind11', 'numpy'],
-    tests_require=["pytest"]
-)

+ 0 - 34
tests/test_gate.py

@@ -1,34 +0,0 @@
-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")

+ 0 - 71
tests/test_gate_application.py

@@ -1,71 +0,0 @@
-import qcgpu
-from qcgpu import State
-import pytest
-import numpy as np
-
-def test_application_x():
-    s = State(3)
-
-    x = qcgpu.gate.x()
-    s.apply_gate(x, 0)
-
-    res = np.array([0,1,0,0,0,0,0,0]).astype(np.complex64).transpose()
-    amps = s.amplitudes()
-
-    assert np.allclose(res, amps)
-
-def test_apply_all_x():
-    s = State(3)
-
-    x = qcgpu.gate.x()
-    s.apply_all(x)
-
-    res = np.array([0,0,0,0,0,0,0,1]).astype(np.complex64).transpose()
-    amps = s.amplitudes()
-
-    assert np.allclose(res, amps)
-
-def test_application_h():
-    s = State(3)
-
-    h = qcgpu.gate.h()
-    s.apply_gate(h, 1)
-
-    res = (1/np.sqrt(2)) * np.array([1,0,1,0,0,0,0,0]).astype(np.complex64).transpose()
-    amps = s.amplitudes()
-
-    assert np.allclose(res, amps)
-
-def test_apply_all_h():
-    s = State(8)
-
-    h = qcgpu.gate.h()
-    s.apply_all(h)
-
-    res = (1 / np.sqrt(2**8)) * np.ones((1, 2**8), dtype=np.complex64)
-    amps = s.amplitudes()
-
-    assert np.allclose(res, amps)
-
-def test_apply_cnot_1():
-    s = State(2)
-
-    x = qcgpu.gate.x()
-    s.apply_controlled_gate(x, 0, 1)
-
-    res = np.array([1,0,0,0]).astype(np.complex64).transpose()
-    amps = s.amplitudes()
-
-    assert np.allclose(res, amps)
-
-def test_apply_cnot_2():
-    s = State(2)
-
-    x = qcgpu.gate.x()
-    s.apply_gate(x, 0)
-    s.apply_controlled_gate(x, 0, 1)
-
-    res = np.array([0,0,0,1]).astype(np.complex64).transpose()
-    amps = s.amplitudes()
-
-    assert np.allclose(res, amps)

+ 0 - 12
tests/test_state.py

@@ -1,12 +0,0 @@
-from qcgpu import State
-import pytest
-
-def test_state_creation():
-    # Any machine should be able to handle 14 qubits
-    for i in range(1, 15):
-        State(i)
-
-def test_state_with_no_qubits_fails():
-    with pytest.raises(Exception):
-        State(0)
-

+ 0 - 12
working.py

@@ -1,12 +0,0 @@
-import qcgpu
-import time
-
-s = qcgpu.State(28)
-h = qcgpu.gate.h()
-
-s.apply_all(h)
-
-
-
-print(s.measure(1000))
-# print(s.backend.measure(samples=10000))