Commit f4e97b27 authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

Merge branch 'master' of https://github.com/ornl-qci/xacc

parents 1799fbef e21c8250
......@@ -44,6 +44,7 @@ ExternalProject_Add(cppmicroservices
GIT_TAG v3.1.0
CMAKE_ARGS -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} install
......@@ -60,6 +61,7 @@ ExternalProject_Add(cpprestsdk
CONFIGURE_COMMAND ${CMAKE_COMMAND} ../cpprestsdk/Release/ -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
-DOPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR}
-DBUILD_TESTS=OFF
......
D-Wave Integration
===================
D-Wave
=======
Installation
------------
.. note::
If you want support for the D-Wave Accelerator, you must install
`CppRestSDK <https://github.com/microsoft/cpprestsdk>`_ and OpenSSL. This
is required for making remote HTTP Rest calls to the D-Wave server APIs.
Here's how to install these as binaries on various popular platforms:
.. code::
$ (macosx) brew install cpprestsdk
$ (fedora) dnf install cpprest-devel openssl-devel
$ (ubuntu) apt-get install libcpprest-dev libssl-dev
$ (spack) spack install cpprestsdk
$ (spack) spack install openssl
The `D-Wave Plugin <https://github.com/ornl-qci/xacc-dwave>`_ provides
support to XACC for executing programs on the D-Wave QPU via the D-Wave Accelerator.
......@@ -28,19 +12,6 @@ To install this plugin, run the following
$ xacc-install-plugins.py -p xacc-dwave
.. note::
It has been observed on Mac OS X that the above command may fail
due to CMake incorrectly finding OpenSSL. If that happens, run the
following:
.. code::
$ xacc-install-plugins.py -p xacc-dwave -a OPENSSL_ROOT_DIR=/usr/local/opt/openssl
Homebrew creates the above OpenSSL root directory. If yours is different, then
set the ``OPENSSL_ROOT_DIR`` as such.
You have now installed the D-Wave plugin. It is located in ``$XACC_ROOT/lib/plugins/accelerator`` and ``$XACC_ROOT/lib/plugins/compilers``, where XACC_ROOT is your XACC install prefix.
Extensibility for Minor Graph Embedding Algorithms
......
IBM Integration
================
IBM
===
Installation
-------------
.. note::
If you want support for the IBM Accelerator, you must install
`CppRestSDK <https://github.com/microsoft/cpprestsdk>`_ and OpenSSL. This
is required to make remote HTTP Rest calls to the IBM Quantum Experience
server APIs. Here's how to install these as binaries on various popular platforms:
.. code::
$ (macosx) brew install cpprestsdk
$ (fedora) dnf install cpprest-devel openssl-devel
$ (ubuntu) apt-get install libcpprest-dev libssl-dev
$ (spack) spack install cpprestsdk
$ (spack) spack install openssl
The `IBM Plugin <https://github.com/ornl-qci/xacc-ibm>`_ provides
support to XACC for executing programs
on the IBM Quantum Experience via the IBM Accelerator.
......@@ -28,23 +12,45 @@ To install this plugin, run the following
.. code::
$ xacc-install-plugins.py -p xacc-ibm
$ xacc-install-plugins.py -p ibm
.. note::
You have now installed the IBM plugin. It is located in ``$XACC_ROOT/lib/plugins/accelerators``,
where ``XACC_ROOT`` is your XACC install prefix.
It has been observed on Mac OS X that the above command may fail
due to CMake incorrectly finding OpenSSL. If that happens, run the
following:
.. code::
$ xacc-install-plugins.py -p xacc-ibm -a OPENSSL_ROOT_DIR=/usr/local/opt/openssl
Setting Credentials
-------------------
Homebrew creates the above OpenSSL root directory. If yours is different, then
set the ``OPENSSL_ROOT_DIR`` as such.
In order to target the IBM Quantum Experience, you must provide XACC with your API key.
To do so, open the file ``$HOME/.ibm_config``, and add the following contents
You have now installed the IBM plugin. It is located in ``$XACC_ROOT/lib/plugins/accelerator``,
where ``XACC_ROOT`` is your XACC install prefix.
.. code:: bash
key: YOUR_API_KEY
url: https://quantumexperience.mybluemix.net
Alternatively, any application built on the XACC framework with IBM plugins available
will expose ``-ibm-api-url`` and ``--ibm-api-key`` command line arguments:
.. code:: bash
$ ./my-xacc-app --ibm-api-key YOUR_API_KEY --ibm-api-url https://quantumexperience.mybluemix.net
IBM Command Line Arguments
---------------------------
The IBM plugin exposes the following command line arguments
+------------------------+----------------------------------------+
| Argument | Description |
+========================+========================================+
| --ibm-backend | The backend to target (e.g. ibmqx5) |
+------------------------+----------------------------------------+
| --ibm-shots | The number of shots to execute per job |
+------------------------+----------------------------------------+
| --ibm-list-backends | List the available backends |
+------------------------+----------------------------------------+
| --ibm-shots | The number of shots to execute per job |
+------------------------+----------------------------------------+
Hydrogen VQE Example
---------------------
......@@ -58,70 +64,69 @@ kernel code for this example can be found in `Scalable Quantum Simulation of Mol
This example requires Scaffold. See `Install Scaffold <scaffold.html>`_ for
installation details.
.. code-block:: cpp
#include "XACC.hpp"
const std::string src(""
"__qpu__ initializeState(qbit qreg, float theta) {\n"
" Rx(qreg[0], 3.1415926);\n"
" Ry(qreg[1], 1.57079);\n"
" Rx(qreg[0], 7.8539752);\n"
" CNOT(qreg[1], qreg[0]);\n"
" Rz(qreg[0], theta);\n"
" CNOT(qreg[1], qreg[0]);\n"
" Ry(qreg[1], 7.8539752);\n"
" Rx(qreg[0], 1.57079);\n"
"}\n"
""
"__qpu__ g1Term (qbit qreg, float theta) {\n"
" initializeState(qreg, theta);\n"
" cbit creg[1];\n"
" creg[0] = MeasZ(qreg[0]);\n"
"}\n"
""
"__qpu__ g2Term (qbit qreg, float theta) {\n"
" initializeState(qreg, theta);\n"
" cbit creg[1];\n"
" creg[0] = MeasZ(qreg[1]);\n"
"}\n"
"__qpu__ g3Term (qbit qreg, float theta) {\n"
" initializeState(qreg, theta);\n"
" cbit creg[2];\n"
" creg[1] = MeasZ(qreg[1]);\n"
" creg[0] = MeasZ(qreg[0]);\n"
"}\n"
"__qpu__ g4Term(qbit qreg, float theta) {\n"
" initializeState(qreg, theta);\n"
" cbit creg[2];\n"
" Rx(qreg[1], 1.57079);\n"
" Rx(qreg[0], 1.57079);\n"
" creg[1] = MeasZ(qreg[1]);\n"
" creg[0] = MeasZ(qreg[0]);\n"
"}\n"
""
"__qpu__ g5Term(qbit qreg, float theta) {\n"
" initializeState(qreg, theta);\n"
" cbit creg[2];\n"
" H(qreg[1]);\n"
" creg[1] = MeasZ(qreg[1]);\n"
" H(qreg[0]);\n"
" creg[0] = MeasZ(qreg[0]);\n"
"}\n"
"");
const std::string src = R"src(
__qpu__ initializeState(qbit qreg, float theta) {
Rx(qreg[0], 3.1415926);
Ry(qreg[1], 1.57079);
Rx(qreg[0], 7.8539752);
CNOT(qreg[1], qreg[0]);
Rz(qreg[0], theta);
CNOT(qreg[1], qreg[0]);
Ry(qreg[1], 7.8539752);
Rx(qreg[0], 1.57079);
}
__qpu__ g1Term (qbit qreg, float theta) {
initializeState(qreg, theta);
cbit creg[1];
creg[0] = MeasZ(qreg[0]);
}
__qpu__ g2Term (qbit qreg, float theta) {
initializeState(qreg, theta);
cbit creg[1];
creg[0] = MeasZ(qreg[1]);
}
__qpu__ g3Term (qbit qreg, float theta) {
initializeState(qreg, theta);
cbit creg[2];
creg[1] = MeasZ(qreg[1]);
creg[0] = MeasZ(qreg[0]);
}
__qpu__ g4Term(qbit qreg, float theta) {
initializeState(qreg, theta);
cbit creg[2];
Rx(qreg[1], 1.57079);
Rx(qreg[0], 1.57079);
creg[1] = MeasZ(qreg[1]);
creg[0] = MeasZ(qreg[0]);
}
__qpu__ g5Term(qbit qreg, float theta) {
initializeState(qreg, theta);
cbit creg[2];
H(qreg[1]);
creg[1] = MeasZ(qreg[1]);
H(qreg[0]);
creg[0] = MeasZ(qreg[0]);
}
)src";
int main (int argc, char** argv) {
// Initialize the XACC Framework
xacc::Initialize(argc, argv);
// Create a reference to the Rigetti
// QPU at api.rigetti.com/qvm
// Create a reference to the IBM
// QPU at the IBM Quantum Experience
auto qpu = xacc::getAccelerator("ibm");
// Allocate a register of 3 qubits
auto qubitReg = qpu->createBuffer("qreg", 2);
// Allocate a register of 2 qubits
auto qubitReg = qpu->createBuffer(qreg, 2);
// Create a Program
xacc::Program program(qpu, src);
......@@ -130,7 +135,7 @@ kernel code for this example can be found in `Scalable Quantum Simulation of Mol
// the above source code
auto kernels = program.getKernels<float>();
std::ofstream file("out.csv");
file << "Angle, Z0, Z1, Z0Z1, Y0Y1, X0X1\n";
file << "Angle, Z0, Z1, Z0Z1, Y0Y1, X0X1";"
auto pi = 3.14159265359;
for (float theta = -pi; theta <= pi; theta += .2) {
......@@ -140,15 +145,15 @@ kernel code for this example can be found in `Scalable Quantum Simulation of Mol
// Skip the first kernel, it is the state prep
// kernel that all others will call anyway
for (int i = 1; i < kernels.size(); i++) {
file << ", ";
std::cout << "Executing Kernel " << i << "\n";
file << , ;
std::cout << "Executing Kernel " << i << ;
kernels[i](qubitReg, theta);
std::cout << "Done Executing Kernel " << i << "\n";
std::cout << "Done Executing Kernel" << i << ;
auto e = qubitReg->getExpectationValueZ();
qubitReg->resetBuffer();
file << e;
}
file << "\n";
file << ;
file.flush();
}
......
......@@ -11,14 +11,15 @@ Welcome to XACC's documentation!
:caption: Contents:
overview
install
api
install
python
scaffold
tnqvm
rigetti
ibm
dwave
xacc-vqe
......
......@@ -11,30 +11,44 @@ The following third party libraries (TPLs) are used by XACC:
+------------------------+------------+-----------+
| Packages | Dependency | Version |
+========================+============+===========+
| C++14 Compiler | Required | See below |
| C++11 Compiler | Required | See below |
+------------------------+------------+-----------+
| Boost | Required | 1.59.0+ |
+------------------------+------------+-----------+
| MPI | Optional | N/A |
| OpenSSL | Required | 1.0.2 |
+------------------------+------------+-----------+
| CMake | Required | 3.2+ |
+------------------------+------------+-----------+
Note that you must have a C++14 compliant compiler.
For GCC, this means version 6.1+, for Clang, this means 3.4+.
Note that you must have a C++11 compliant compiler.
For GCC, this means version 4.8.1+, for Clang, this means 3.3+.
These dependencies are relatively easy to install on popular operating
systems. Any of the following commands will work (showing with and without MPI):
These dependencies are relatively easy to install on various operating
systems. Any of the following commands will work for Mac, Fedora/RedHat/CentOS, or Ubuntu:
.. code::
$ (macosx) brew install boost
$ (macosx) brew install boost-mpi
$ (macosx) brew/port install boost openssl
$ (fedora) dnf install boost-devel
$ (fedora) dnf install boost-mpich-devel
$ (fedora) dnf install boost-openmpi-devel
$ (ubuntu) apt-get install libboost-all-dev # will install openmpi
$ (ubuntu) apt-get install libboost-all-dev
.. note::
On Fedora, the latest version of OpenSSL available via DNF is 1.1.1. This
version of OpenSSL is not compatible with CppRestSDK, a library that XACC
leverages to connect to remote Accelerators. To install OpenSSL from source
Build XACC
-----------
.. code::
$ wget https://www.openssl.org/source/openssl-1.0.2n.tar.gz
$ tar -xvzf openssl-1.0.2n.tar.gz
$ cd openssl-1.0.2h
$ CFLAGS=-fPIC ./config shared (--prefix=/path/to/install if you want)
$ make
$ make install
Building XACC
-------------
Clone the XACC repository:
......@@ -51,114 +65,77 @@ configure and build XACC:
$ cmake ..
$ make install # can pass -jN for N = number of threads to use
This will build, test, and install XACC to ``/usr/local/xacc``
(Pass ``-DCMAKE_INSTALL_PREFIX=$YOURINSTALLPATH`` to install it somewhere else).
Set your PATH variable to include the XACC bin directory:
This will build, test, and install XACC to ``/usr/local/xacc``. If you don't have
root access, and therefore can't write to ``/usr/local/xacc``, or would like to just
install XACC somewhere else, replace the above ``cmake`` command with the following
.. code::
$ export PATH=/usr/local/xacc/bin:$PATH
Additionally, you could add this to your home directory's ``.basrhc`` file (or equivalent).
$ cmake .. -DCMAKE_INSTALL_PREFIX=/path/to/local/install
Installing XACC Plugins
-----------------------------------
If you have successfully built XACC (see above)
then you can now run
After running CMake, you should see that OpenSSL was found. If there is
a problem with finding OpenSSL 1.0.2, you can point XACC to OpenSSL with
.. code::
$ xacc-install-plugins.py --help
This is a convenience python script to help download, build, and install
all currently supported XACC plugins. The execution syntax is as follows:
.. code::
.. code:: bash
$ xacc-install-plugins.py -p PLUGIN-NAME
$ cmake .. -DOPENSSL_ROOT_DIR=/path/to/openssl
You can also run this script with multiple plugin names.
The CMake configure will also look for Python development libraries on your
system, and if found, will generate the `XACC Python Bindings <python.html>`_ bindings.
If XACC does not find your correct Python installation, you can point to it with
.. code::
$ xacc-install-plugins.py -p PLUGIN1 PLUGIN2 PLUGIN3
.. code:: bash
You can also pass CMake arguments to this script. For example, if you
wanted to specify the path to your OpenSSL install for a plugin
that depended on OpenSSL, you could run the following
$ cmake .. -DPYTHON_EXECUTABLE=/path/to/python
.. code::
At this point, if you like, you can setup your Python environment
to automatically load the XACC Python bindings with
$ xacc-install-plugins.py -p PLUGIN-NAME -a OPENSSL_ROOT_DIR=/usr/local/opt/openssl
.. code:: bash
You can pass multiple CMake arguments at once.
$ export PYTHONPATH=$PYTHONPATH:/usr/local/xacc/lib/python
XACC and Spack
---------------
You can build XACC and its dependencies with the `Spack
<https://github.com/llnl/spack>`_ package manager.
or ``$YOURINSTALLPATH/lib/python``.
To configure your available system compilers run
You may also set your PATH variable to include the XACC bin directory:
.. code::
$ spack compilers
.. note::
If you run 'spack config get compilers' and your desired
compiler has fc and f77 set to Null or None, then the
install will not work if you are including MPI support.
If this is the case, it usually
works to run 'spack config edit compilers' and
manually replace Null with /path/to/your/gfortran
$ export PATH=/usr/local/xacc/bin:$PATH
We will rely on the environment-modules package to load/unload
installed Spack modules. If you don't have this installed
(you can check by running 'module avail') install with
or wherever you installed XACC to (``$YOURINSTALLPATH/bin``).
.. code::
Additionally, you may want to add these exports
to your home directory's ``.basrhc`` file (or equivalent).
$ spack install environment-modules
Add the following to your ~/.bashrc (or equivalent)
Installing XACC Plugins
------------------------
If you have successfully built XACC (see above)
then you can now run
.. code::
. $SPACK_ROOT/share/spack/setup-env.sh
source $(spack location -i environment-modules)/Modules/init/bash
$ xacc-install-plugins.py --help
If you do not have a C++14 compliant compiler, you can
install one with Spack, for example
This is a convenience python script to help download, build, and install
all currently supported XACC plugins. The execution syntax is as follows:
.. code::
$ spack install gcc@7.2.0 # this will take awhile...
$ spack load gcc
$ spack compiler find
$ xacc-install-plugins.py -p PLUGIN-NAME
XACC has not yet been accepted into the Spack (we will soon issue a PR
to get it shipped as part of Spack). So in order to install it with Spack
we have to download our custom package recipe from the XACC repository:
You can also run this script with multiple plugin names.
.. code::
$ cd $SPACK_ROOT/var/spack/repos/builtin/packages/ && mkdir xacc
$ cd xacc && wget https://github.com/ORNL-QCI/xacc/raw/master/cmake/spack/xacc/package.py .
$ xacc-install-plugins.py -p PLUGIN1 PLUGIN2 PLUGIN3
Now we can run
and pass CMake arguments to this script. For example, if you
wanted to specify the argument ``CMAKEARG`` for a plugin, you could run the following
.. code::
$ (without MPI support) spack install xacc
$ (with MPI support) spack install xacc +mpi
$ (with specified compiler) spack install xacc %gcc@7.2.0
Update your PATH to point to the XACC ``bin`` directory:
.. code::
$ xacc-install-plugins.py -p PLUGIN-NAME -a CMAKEARG=arg
$ export PATH=$(spack location -i xacc)/bin:$PATH
You can also pass multiple CMake arguments at once.
We recommend you add this command to you ``.bashrc`` file (or equivalent).
......@@ -37,4 +37,7 @@ new issue with the question tag.
Publications and Presentations
-------------------------------
`Extreme-Scale Programming Model for Quantum Acceleration within High Performanc Computing <https://arxiv.org/abs/1710.01794>`_
`Cloud Quantum Computing of an Atomic Nucleus <https://arxiv.org/abs/1801.03897>`_
XACC Plugins
=============
Rigetti
--------
Rigetti Computing, Inc (`rigetti.com <rigetti.com>`_) is a recently founded startup that is focused on
developing quantum computing hardware and software and bring it to market.
They are working to build a cloud quantum computing platform for AI and
computational chemistry. They currently have a QVM simulation server
that can be accessed via a REST API with a private API key. Rigetti has
also done great work as of late in providing open source programming tools for
interfacing with their QVM - specifically, the PyQuil python framework
`PyQuil <https://github.com/rigetticomputing/pyquil>`_.
Recently, the ORNL QCI `(quantum.ornl.gov) <http://quantum.ornl.gov>`_, the XACC project,
and the Software and Applications Team from Rigetti have begun collaborating in
an effort to expose the Rigetti QVM server and programming tools to XACC and its user
community. This article describes the results of that work - specifically, a
new XACC Accelerator implementation that executes quantum kernels on the
Rigetti QVM server. For a more hands-on tutorial on how to use XACC and the Rigetti
Accelerator, check out `Rigetti Tutorial <tutorials.html#Rigetti QVM Tutorial>`_).
RigettiAccelerator
^^^^^^^^^^^^^^^^^^^
The RigettiAccelerator is an implementation or realization of the pluggable
XACC Accelerator interface. The RigettAccelerator class architecture diagram is
shown in Figure 1. The RigettiAccelerator's implementation of the Accelerator::execute() method
is charged with two primary tasks: (1) the translation of the XACC IR to an equivalent
Quil string, and (2) constructing and executing an
appropriate HTTPS Post on the Rigetti QVM server. The only remaining
thing to do once those two tasks are complete is to processes the resultant response from the server.
.. image:: ../../assets/rigetti-acc-arch.png
Mapping XACC IR to Quil
^^^^^^^^^^^^^^^^^^^^^^^^
Basically,
at its core, the XACC IR provides a tree-like, in-memory representation and API for a
compiled quantum kernel. The leaves of this tree are XACC Instructions and the nodes
of the tree are XACC Functions, which are composed of further child Instructions. The
XACC Quantum IR implementation provides a number of standard gate Instruction implementations
(Hadamard, CNOT, rotations, etc...) These serve as the leaves of the IR tree. These
instruction implementations know nothing of the Quil intermediate language and it would be tedious
and a poor design decision to to update the entire XACC Quantum IR package (we would have to do the
same for any and all current and future low-level languages). So XACC employs a common
software engineering design pattern to enable this XACC IR to Quil mapping: the
visitor pattern, which provides a mechansim for adding new operations to an
existing object without modifying the design of that object (`Visitor Pattern <https://en.wikipedia.org/wiki/Visitor_pattern>`_). For each derived gate Instruction, a Visitor class implements a
corresponding ```visit``` method (```visit(Hadamard& h)```, etc...). All gate instructions have the
ability to accept an incoming Visitor, and upon doing so, invoke the ```visit``` method that
corresponds to their type, thus giving the Visitor type information for the Gate Instruction.
Therefore, mapping to Quil simply involves walking the IR tree, and telling each Instruction to
accept the visitor:
.. code::
auto visitor = std::make_shared<QuilVisitor>();
InstructionIterator it(kernel);
while (it.hasNext()) {
// Get the next node in the tree
auto nextInst = it.next();
if (nextInst->isEnabled()) nextInst->accept(visitor);
}
auto quilStr = visitor->getQuilString();
The visitor implementation is known as the QuilVisitor, and its visit methods look like this (Hadamard for example):
.. code::
void visit(Hadamard& h) {
quilStr += "H " + std::to_string(h.bits()[0]) + "\n";
}
or for a more complicated gate Instruction:
.. code::
void visit(ConditionalFunction& c) {
auto visitor = std::make_shared<QuilVisitor>();
auto classicalBitIdx = qubitToClassicalBitIndex[c.getConditionalQubit()]; // populated in visit(Measure)
quilStr += "JUMP-UNLESS @" + c.getName() + " [" + std::to_string(classicalBitIdx) + "]\n";
for (auto inst : c.getInstructions()) {