Skip to content

Commit

Permalink
Adding hybrid compute sample app (#82)
Browse files Browse the repository at this point in the history
* Adding hybrid compute sample application
---------

Co-authored-by: Sean Huver <[email protected]>
  • Loading branch information
jjomier and huvers authored Sep 6, 2023
1 parent e976752 commit 570d894
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 0 deletions.
58 changes: 58 additions & 0 deletions applications/cuda_quantum/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Hybrid-Computing Sample App - CUDA Quantum Variational Quantum Eigensolver (VQE) Application

## Variational Quantum Eigensolver (VQE)
The Variational Quantum Eigensolver (VQE) is a quantum algorithm designed to approximate the ground state energy of quantum systems. This energy, represented by what is called the Hamiltonian of the system, is central to multiple disciplines, including drug discovery, material science, and condensed matter physics. The goal of VQE is to find the state that minimizes the expectation value of this Hamiltonian, which corresponds to the ground state energy.

At its core, VQE is a lighthouse example of the synergy between classical and quantum computing, requiring them both to tackle problems traditionally deemed computationally intractable. Even in the current landscape where fault-tolerant quantum computing—a stage where quantum computers are resistant to errors—is not yet realized, VQE is seen as a practical tool. This is due to its design as a 'near-term' algorithm, built to operate on existing noisy quantum hardware.

## Key Components of VQE
1. **Hamiltonian**: This represents the total energy of the quantum system, which is known ahead of time. In VQE, we aim to find the lowest eigenvalue (ground state energy) of this Hamiltonian.

2. **Ansatz (or trial wavefunction)**: The ansatz is the initial guess for the state of the quantum system, represented by a parameterized quantum circuit. It's crucial for this state to be a good representation, as the quality of the ansatz can heavily influence the final results. VQE iteratively refines the parameters of this ansatz to approximate the true ground state of the Hamiltonian.

## VQE Mechanism
The VQE operates by employing a hybrid quantum-classical approach:

1. **Quantum Circuit Parameterization**: VQE begins with a parameterized quantum circuit, effectively serving as an initial guess or representation of the system's state.
2. **Evaluation and Refinement**: The quantum system's energy is evaluated using the current quantum circuit parameters. Classical optimization algorithms then adjust these parameters in a quest to minimize the energy.
3. **Iterative Process**: The combination of quantum evaluation and classical refinement is iterative. Over multiple cycles, the parameters are tuned to get increasingly closer to the true ground state energy.

## Integration with Holoscan and CUDA Quantum
- **NVIDIA Holoscan SDK**: The Holoscan SDK is designed for efficient handling of high-throughput, low-latency GPU tasks. Within the context of VQE, the Holoscan SDK facilitates the rapid classical computations necessary for parameter adjustments and optimization. The `ClassicalComputeOp` in the provided code sample is an example of this SDK in action, preparing the quantum circuits efficiently.
- **CUDA Quantum**: CUDA Quantum is a framework that manages hybrid quantum-classical workflows. For VQE, CUDA Quantum processes quantum data and executes quantum operations. The `QuantumComputeOp` operator in the code uses the cuQuantum simulator backend, but the user may optionally switch out the simulator for a real quantum cloud backend provided by either IonQ or Quantinuum ([see CUDA Quantum backend documentation](https://nvidia.github.io/cuda-quantum/latest/using/hardware.html#)).

Holoscan ensures swift and efficient classical computations, while CUDA Quantum manages the quantum components with precision.

## Usage

To run the application, you need to have CUDA Quantum, Qiskit, and Holoscan installed. You also need an IBM Quantum account to use their quantum backends.

1. Clone the repository and navigate to the `cuda_quantum` directory containing.

2. Install the requirements `pip install -r requirements.txt`

3. Either use or replace the `'hamiltonian'` in `cuda_quantum.yaml` dependent on the physical system you wish to model.

4. Run the application with the command `python cuda_quantum.py`.

## Operators

The application uses three types of operators:

- `ClassicalComputeOp`: This operator performs classical computations. It also creates a quantum kernel representing the initial ansatz, or guess of the state of the system, and a Hamiltonian.

- `QuantumComputeOp`: This operator performs quantum computations. It uses the quantum kernel and Hamiltonian from `ClassicalComputeOp` to iterate towards the ground state energy and parameter using VQE.

- `PrintOp`: This operator prints the result from `QuantumComputeOp`.

## Operator Connections

The operators are connected as follows:

```mermaid
flowchart LR
ClassicalComputeOp --> QuantumComputeOp
QuantumComputeOp --> PrintOp
```

`ClassicalComputeOp` sends the quantum kernel and Hamiltonian to `QuantumComputeOp`, which computes the energy and parameter and sends the result to `PrintOp`.
112 changes: 112 additions & 0 deletions applications/cuda_quantum/cuda_quantum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# SPDX-FileCopyrightText: Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os

import cudaq
from cudaq import spin # noqa: F401
from holoscan.conditions import CountCondition
from holoscan.core import Application, Operator, OperatorSpec


class ClassicalComputeOp(Operator):
def __init__(self, *args, hamiltonian, **kwargs):
self.count = 0
self.hamiltonian = hamiltonian
super().__init__(*args, **kwargs)

def setup(self, spec: OperatorSpec):
spec.output("Hamiltonian")
spec.output("QuantumKernel")

def compute(self, op_input, op_output, context):
kernel, thetas = cudaq.make_kernel(list)
qubits = kernel.qalloc(2)
kernel.x(qubits[0])
kernel.ry(thetas[0], qubits[1])
kernel.cx(qubits[1], qubits[0])

print("Printing Circuit: ", kernel)

self.count += 1

op_output.emit(self.hamiltonian, "Hamiltonian")
op_output.emit(kernel, "QuantumKernel")


class QuantumComputeOp(Operator):
def __init__(self, *args, backend_name, api_key=None, **kwargs):
self.backend_name = backend_name
self.api_key = api_key
super().__init__(*args, **kwargs)

def setup(self, spec: OperatorSpec):
spec.input("Hamiltonian")
spec.input("QuantumKernel")
spec.output("Result")

def compute(self, op_input, op_output, context):
hamiltonian = eval(op_input.receive("Hamiltonian"))
kernel = op_input.receive("QuantumKernel")

optimizer = cudaq.optimizers.COBYLA()

energy, parameter = cudaq.vqe(
kernel=kernel, spin_operator=hamiltonian, optimizer=optimizer, parameter_count=1
)

result = "energy: " + str(energy) + "\n parameter: " + str(parameter)
op_output.emit(result, "Result")


class PrintOp(Operator):
def __init__(self, *args, prompt="Result: ", **kwargs):
self.prompt = prompt
super().__init__(*args, **kwargs)

def setup(self, spec: OperatorSpec):
spec.input("text")

def compute(self, op_input, op_output, context):
text = op_input.receive("text")
print(self.prompt, text + "\n")


class QuantumVQEApp(Application):
def compose(self):
classical_computer_operator = ClassicalComputeOp(
self,
CountCondition(self, count=1),
name="classical_op",
**self.kwargs("ClassicalComputeOp"),
)
quantum_computer_operator = QuantumComputeOp(
self, name="Quantum Ops", **self.kwargs("QuantumComputeOp")
)
print_result = PrintOp(self, name="print_result", prompt="VQE Result: ")

self.add_flow(
classical_computer_operator,
quantum_computer_operator,
{("Hamiltonian", "Hamiltonian"), ("QuantumKernel", "QuantumKernel")},
)
self.add_flow(quantum_computer_operator, print_result, {("Result", "text")})


if __name__ == "__main__":
app = QuantumVQEApp()
config_file = os.path.join(os.path.dirname(__file__), "cuda_quantum.yaml")
app.config(config_file)
app.run()
25 changes: 25 additions & 0 deletions applications/cuda_quantum/cuda_quantum.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
%YAML 1.2
# SPDX-FileCopyrightText: Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
---
ClassicalComputeOp:
hamiltonian: 5.907 - 2.1433 * spin.x(0) * spin.x(1) - 2.1433 * spin.y(0) * spin.y(1) + .21829 * spin.z(0) - 6.0 * spin.z(1)

QuantumComputeOp:
api_key: 'IonQ Key Here'
backend_name: 'qpu.aria-1'

# You can replace 'IonQ' with a different IBM quantum backend if needed.

39 changes: 39 additions & 0 deletions applications/cuda_quantum/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"application": {
"name": "cuda_quantum",
"authors": [
{
"name": "Sean Huver",
"affiliation": "NVIDIA"
}
],
"language": "Python",
"version": "1.0.0",
"changelog": {
"1.0.0": "Initial release of cuda_quantum application"
},
"holoscan_sdk": {
"minimum_required_version": "0.6.0",
"tested_versions": [
"0.6.0"
]
},
"platforms": [
"amd64",
"arm64"
],
"tags": [
"Quantum Computing",
"CUDA",
"VQE"
],
"ranking": 4,
"dependencies": {
"cuda_quantum": "^0.4.0"
},
"run": {
"command": "python3 cuda_quantum.py",
"workdir": "holohub_bin"
}
}
}
2 changes: 2 additions & 0 deletions applications/cuda_quantum/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cuda_quantum
holoscan

0 comments on commit 570d894

Please sign in to comment.