Skip to content

Commit

Permalink
Merge pull request #644 from SRI-International/restructure-for-apis
Browse files Browse the repository at this point in the history
Restructure for apis
  • Loading branch information
rtvuser1 authored Oct 18, 2024
2 parents 6ef6304 + 73d6c3f commit f1c4729
Show file tree
Hide file tree
Showing 7 changed files with 816 additions and 253 deletions.
85 changes: 85 additions & 0 deletions _setup/cudaq/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Quantum Computing - Toolkit Information

# CUDA Quantum Version

This directory describes the requirements and operational conventions for using CUDA Quantum as the programming environment for running the benchmark programs contained in the QC-App-Oriented-Benchmarks repository.
In particular, this document explains how to set up the tools needed to run the CUDA Quantum implementation of these benchmarks.

## IMPORTANT Note about Benchmark Directory Structure for CUDA Quantum

Integrating CUDA Quantum into the QED-C benchmarking suite prompted a restructuring of all the benchmark source code in the repository to consolidate common code in a reusable fashion, shareable across API implementations. This effort is a WORK-IN-PROGRESS and has been only partially completed across the suite of benchmarks. In particular, the restructuring defines a shared module for each problem definition and its benchmark looping logic, while isolating code that is specific to each API into a unique quantum "kernel" for that problem definition.

With this strucutre, used by the CUDA Quantum version of the benchmarks, the main routine for each benchmark resides at the top level of the benchmark directory, while the kernels are situated one level deeper in a directory identifed by the API name. For example, the Bernstein-Vazirani benchmark main program is contained in:

bernstein-vazirani/bv_benchmark.py

While the CUDA Quantum implementation of the quantum kernel for this benchmark is in:

bernstein-vazirani/cudaq/bv_kernel.py

As of now, 4 of the benchmarks have been implemented for CUDA Quantum, with kernels contained within the **cudaq** sub-directory for each: **berstein-vazirani, hidden-shift, quantum-fourier transfor, and phase-estimation**. More coming soon. Instructions for running benchmarks on CUDA Quantum are presented below.

Note that for the Qiskit version of the benchmarks, we retained a version of the benhcmark main program in the **qiskit** sub-directory, in order to provide backwards compatibility for users, during this transition period and until the change has been implemented across the entire suite.


## Configure a CUDA Quantum Environment

There are two ways in which the QED-C benchmarks can be executed using CUDA Quantum. These are described in this section. (Note: more detail could be added here, but this info is provided to get users started)

### Run within the CUDA Quantum Docker Container

This is the easiest way to execute the benchmarks with CUDA Quantum. After cloning the QED-C repository into a directory within your container, simply change directory to the top level of the QED-C repository. You then can bring up a Jupyter Notebook to enable execution of all the benchmarks there or you can change directory to any of the available benchmark directories and execute that benchmark on the command line.

Alternatively, you may want to clone the QED-C repository outisde the CUDA Quantum container, and map the directory to a shared volume within the container. This method will provide persistence of the data generated by the benchmarks if the container is stopped and removed (to update to a newer version of CUDA Quantum, for example).

To start a Jupyter notebook within the CUDA Quantum container and make the port available outside, it is recommended that you start Jupyter with a command similar to the following:

jupyter notebook --ip 0.0.0.0 --no-browser --allow-root

When starting the container, you will also need to map the port used by the Jupyter notebook, using a Docker option like this, where 8888 is the default Jupyter port:

-p 8888:8888

### Install CUDA Quantum using Pip

Many users will install the CUDA Quantum package directly onto their system and skip the container entirely. After cloning the QED-C repository to a location on your system, simply change directory to the top level of the QED-C repository. You then can bring up a Jupyter Notebook to enable execution of all the benchmarks there or you can change directory to any of the available benchmark directories and execute that benchmark on the command line.

In addition to the CUDA Quantum package, the benchmarks require two other Python packages and, optionally, the Jupyter notebook package.

pip install numpy matplotlib notebook

Once installed, you are ready to run the benchmark programs.

In the section below, we provide some instructions for executing the benchmarks in either of these modes.

## Run the benchmark programs in a command window.

To execute the benchmarks in a command or shell window, you simply change directory to the desired benchmark directory and execute the benchmark program as follows:

cd [your github home directory]\QC-App-Oriented-Benchmarks\bernstein-vazirani

python bv_benchmark.py -a cudaq

This command instructs the benchmark program to exeucte using the CUDA Quantum kernel. By default, the benchmark will sweep over qubits widths from 2 to 24 qubits. As it executes, the benchmark program will report the benchmark metrics to the console, save them to a data file, and also generate a set of plots depicting the results.

A variety of execution options are available and can be obtained using the -h option for help information:

python bv_benchmark.py -h

The other benchmarks follow a similar format and structure and are executed in the same way (using the appropriate benchmark pgrogram filename).

## Run the benchmark programs in a Jupyter Notebook

Many Python users prefer to execute their Python programs in a Jupyter notebook, which is available in installed in your environment.
Execute the following commands to change directory to one that contains a Jupyter notebook and execute and invoke Jupyter notebook server.

cd [your github home directory]\QC-App-Oriented-Benchmarks]
jupyter-notebook

You can then select the **benchmarks-cudaq.ipynb** notebook in a new browser tab. The first cell of the notebook contains the execution options available for configuration. Subsequent cells contain the run command for each of the benchmarks and can be executed one at a time. To run all the benchmarks simply use the Jupyter Notebook's Run All menu option.

## Tested Versions

Python Versions: 3.10 through 3.12

Earlier (or later) versions of the software might work without issues, but the benchmark has been specifically validated on these versions. If you have any issues installing, please raise an bug report in the issues tab of the repository.
2 changes: 1 addition & 1 deletion _setup/ocean/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Quantum Computing - Toolkit Information

# Qiskit Version
# Ocean Version

This directory describes the requirements and operational conventions for using Ocean as the programming environment for running the benchmark programs contained in the QC-App-Oriented-Benchmarks repository.
In particular, this document explains how to set up the tools needed to run the Ocean implementation of these benchmarks.
Expand Down
598 changes: 361 additions & 237 deletions benchmarks-cudaq.ipynb

Large diffs are not rendered by default.

85 changes: 85 additions & 0 deletions hidden-shift/cudaq/hs_kernel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
'''
Hidden Shift Benchmark Program - CUDA Quantum Kernel
(C) Quantum Economic Development Consortium (QED-C) 2024.
'''

import cudaq

from typing import List

# saved circuits for display
QC_ = None
Uf_ = None

############### BV Circuit Definition

# Uf oracle where Uf|x> = f(x)|x>, f(x) = {-1,1}
@cudaq.kernel
def Uf_oracle(qubits: cudaq.qview, num_qubits: int, hidden_bits: list[int]):

for i_qubit in range(num_qubits):
if hidden_bits[num_qubits-1-i_qubit] == 1 :
x(qubits[i_qubit])

for i_qubit in range(0,num_qubits-1,2):
cz(qubits[i_qubit], qubits[i_qubit+1])

for i_qubit in range(num_qubits):
if hidden_bits[num_qubits-1-i_qubit] == 1:
x(qubits[i_qubit])

# Generate Ug oracle where Ug|x> = g(x)|x>, g(x) = f(x+s)
@cudaq.kernel
def Ug_oracle(qubits: cudaq.qview, num_qubits: int):

for i_qubit in range(0,num_qubits-1,2):
cz(qubits[i_qubit], qubits[i_qubit+1])


@cudaq.kernel
def hs_kernel (num_qubits: int, secret_int: int, hidden_bits: List[int], method: int = 1):

# Allocate the specified number of qubits - this
# corresponds to the length of the hidden bitstring.
qubits = cudaq.qvector(num_qubits)

# Start with Hadamard on all input qubits
h(qubits)

# Query the oracle.
#oracle(qubits, auxillary_qubit, hidden_bits)
Uf_oracle(qubits, num_qubits, hidden_bits)

# Apply another set of Hadamards to the qubits.
h(qubits)

Ug_oracle(qubits, num_qubits)

# Apply another set of Hadamards to the qubits.
h(qubits)

# Measure all qubits
mz(qubits)


def HiddenShift (num_qubits: int, secret_int: int, hidden_bits: List[int], method: int = 1):

qc = [hs_kernel, [num_qubits, secret_int, hidden_bits, method]]

global QC_
if num_qubits <= 6:
QC_ = qc

return qc

############### BV Circuit Drawer

# Draw the circuits of this benchmark program
def kernel_draw():
print("Sample Circuit:");
if QC_ != None:
print(cudaq.draw(QC_[0], *QC_[1]))
else:
print(" ... too large!")


Loading

0 comments on commit f1c4729

Please sign in to comment.