Single-Source Pythonic Programming for Quantum-Accelerated Computing with Eclipse XACC
In various scientific and engineering fields, there is a wide range of computational- and data-intensive tasks that require tremendous amounts of energy, time, and other resources to complete. These types of problems, which include the simulation of quantum mechanical systems, molecular modeling, and machine learning, are typically solved with the aid of large-scale, high-performance computing (HPC) systems and resources. Recent trends in HPC have focused on the development of heterogeneous computing architectures that combine many central processing units with dedicated and specialized accelerators. In accelerated computing, certain aspects of a complex problem are offloaded to these dedicated accelerators, such as a graphical processing unit, to take advantage of the device's specialized hardware and design in order to perform functions that would normally be too expensive to perform on a general-purpose processor.
Recently, there have been a number of research efforts into novel, heterogeneous computing architectures that involve the use of quantum processing units (QPU) as accelerators to traditional classical compute nodes. Recent progress in the development and availability of primitive quantum hardware has enabled loose integration with classical architectures in a hybrid computing context, pointing to future tighter integrations similar to traditional accelerated computing. With the advent of potential quantum acceleration, a major focus is being placed on how we can provide high-level programming models and extensible, open-source software to allow for the offloading of select computational tasks to attached quantum accelerators. Luckily, research being done at Oak Ridge National Laboratory on how to provide this important software infrastructure has resulted in the production of Eclipse XACC.
Eclipse XACC is an open-source, hybrid programming model designed to enhance classical software workflows with near-term quantum accelerators . Following a traditional coprocessor model, XACC allows for quantum kernels (C-like functions containing quantum code) to be offloaded to available quantum accelerators while taking into account the intricacies inherent to quantum-classical hybrid computation. XACC accomplishes this using four key abstractions: compilers, accelerators, kernels, and intermediate representations (shown in Figure 1). In XACC, a quantum kernel is a stand-alone representation of quantum instructions and operations (usually represented with circuit diagrams containing one- and two-qubit gate operations) that are to be applied to a register of qubits, similar to conventional accelerated computing kernels. These quantum kernels can express quantum code in any available language for which XACC has a valid compiler. The compiler interface provided by the framework takes the quantum source code and produces an instance of the XACC intermediate representation (IR) to enable analysis, transformation, and/or optimization of the quantum kernel. This intermediate representation is then mapped to a low-level, hardware-native quantum assembly language that is subsequently executed on the target quantum accelerator. Integrating quantum computers with this infrastructure requires an implementation of the accelerator abstraction, which acts as a unified communication protocol or device driver API. This interface is responsible for the remote QPU client interactions and can delegate to both physical and virtual (simulated) QPUs. XACC has accelerator implementations for Rigetti, IBM, and D-Wave QPUs and a suite of simulators. The accelerator interface also exposes an accelerator-buffer concept, which is responsible for modeling a register of qubits and for storing the measurement results obtained from the execution of the quantum kernels on available accelerators.
XACC Python JIT Compiler
The Python programming language is well known for enabling developer productivity with its simple and intuitive syntax and multi-paradigm design. In fact, most existing quantum programming approaches, such as IBM’s Qiskit, Rigetti’s PyQuil, and D-Wave’s Ocean, are Pythonic. This variety of Pythonic programming approaches implies a stove-piped quantum programming landscape―users are forced to learn a new framework (circuit bookkeeping data structures) for each QPU they would like to program. This lack of portability and interoperability of compilers and programming approaches is an impediment for current research efforts and benchmarking approaches. One of the major goals of the Eclipse XACC framework is for users to be able to write and execute quantum programs in a hardware- and language-independent manner, and now, we are moving toward a unified, single-source approach.
Recent updates to Eclipse XACC have enabled an expressive, single-source Pythonic approach for productive programming workflows on near-term quantum computers. XACC provides a novel Python just-in-time (JIT) quantum compilation API that is designed to make offloading and execution of quantum kernels on attached quantum accelerators simple and intuitive. A graphical overview of the XACC Python JIT compilation process and workflow, seen in Figure 2, shows how this process is enabled within the framework. XACC defines Python-source-code annotations (standard Python decorators, e.g., @xacc.qpu()) that, when used to annotate quantum code expressed as a standard Python function, direct the framework to compile the kernel using the PyXACC implementation of the XACC compiler abstraction. The PyXACC compiler delegates to an ANTLR auto-generated parser to build parse trees and tree walkers to compile the Pythonic quantum code into functional instances of XACC IR. The XACC source-code annotations, in the form of Python decorators, contain arguments and directives defined by the user which are then used by XACC to compile to the appropriate desired accelerator as well as any additional options and settings for execution of the quantum kernel. After a quantum kernel has been defined and annotated, the function can be called just like any standard Python function to execute the compilation and execution of the quantum code. The XACC framework affects this execution and then gathers the qubit measurement results and stores them in the appropriate accelerator buffer.
Application: The Binding Energy of Deuteron
To demonstrate Eclipse XACC and the Python JIT compilation process, Figure 3 shows an example of a script that computes the lowest eigenvalue of a given matrix. This eigenvalue corresponds to an estimate of the binding energy of deuteron, the smallest atomic nuclei composed of a single proton and neutron (for more details, see ). A common approach to solving a problem such as this on a quantum computer is to use a hybrid quantum-classical algorithm known as the variational quantum eigensolver (VQE) algorithm. In VQE, a parameterized quantum program (called the ansatz) is used to prepare a state on the quantum computer, followed by execution of distinct qubit measurement operations (dictated by the physics of the system being simulated) that produces an estimate of the minimal eigenvalue we are trying to compute. With this estimate in hand, the parameters of the ansatz are then updated as part of a typical classical function optimization approach (such as Nelder-Mead or gradient descent) until convergence to the lowest eigenvalue
This code sample demonstrates the power and simplicity of this single-source, Pythonic approach to quantum acceleration. First, the XACC framework is initialized (which loads all available compilers, accelerators, etc.) and a reference to the desired quantum accelerator is instantiated, which in this case is a remotely hosted IBM QPU. Next, a register of qubits is allocated (akin to a quantum version of malloc()) on the accelerator. The deuteron Hamiltonian (the matrix whose minimal eigenvalue we seek) is then constructed using appropriate data structures (here, the PauliOperator). Next, a dictionary of Python decorator arguments is constructed that will be passed to the decorator and interpreted by XACC to further compile and execute the quantum program. The arguments in this example specify that this quantum program should be executed as part of the VQE algorithm on the IBM quantum accelerator and that the observable to be measured is the deuteron Hamiltonian defined earlier. Then, a quantum function is defined and wrapped using the @xacc.qpu() decorator, signaling the XACC framework to compile this function at runtime to an instance of the XACC IR. The function definition specifies that it will take two arguments: (1) the accelerator buffer that represents the qubit register to operate on and that will also store the results of the execution, and (2) the single program parameter that will be optimized to compute the binding energy. The body of the function is the parameterized quantum program defined using gate primitives that the XACC compiler will use to build the quantum kernel. The function is then called and the quantum kernel executed, with the results of the execution being stored in the buffer provided.
 A Language and Hardware Independent Approach to Quantum Classical Computing, https://doi.org/10.1016/j.softx.2018.07.007
 Cloud Quantum Computing of an Atomic Nucleus, https://doi.org/10.1103/PhysRevLett.120.210501