Solving arbitrary QUBOs using QAOA

Luna offers more than just its use case library – it's also a versatile tool for solving custom optimization problems you might encounter. In this tutorial, we'll explore a scenario where you've developed a proprietary transformation for a specific use case that you want to keep in-house. This transformation helps convert your optimization problem into the QUBO format. We will then solve this QUBO using QAOA.

In such cases, Luna offers the ability to effortlessly upload your custom optimization problem to your Luna account for storage and processing.

# Load the LunaSolve package
from luna_sdk.controllers import LunaSolve

# Create a Luna object and set your credentials
lunaSolve = LunaSolve(email="YOUREMAIL", password="YOURPASSWORD")

# Define your custom QUBO. It has to be a matrix represented as a list of lists
qubo_matrix = [
    [4, 0, 0, 0, -2],
    [0, -2, 0, 0, 0],
    [0, 0, 6, -3, 0],
    [0, 0, -3, 2, 0],
    [-2, 0, 0, 0, 5]

# Send and store the QUBO
optimization = lunaSolve.optimization.create_from_qubo(name="A Name", matrix=qubo_matrix)

From this point onward, you have the option to select one of our pre-implemented QUBO solver algorithms. You can decide to manually choose your preferred algorithm or use our recommendation engine.

It's important to note that while the recommendation engine can work with raw QUBO formulations, its suggestions may be more accurate when dealing with use cases from our library due to the additional context they provide. Keep this in mind when using this feature.

In this case, let's assume that you want to solve your QUBO using QAOA on one of IBM's quantum hardwares. Specifically, we'll use the least busy backend to retrieve the solution as fast as possible.

# Solve the QUBO using QAOA and the least busy backend from IBM
job = lunaSolve.solution.create(,
        solver_parameters={"backend": "least_busy"}

Depending on the selected quantum hardware, the execution might take some time. To prevent you from waiting for the code to complete, we've designed the process to be asynchronous. When you request a solution, LunaSolve handles all the required steps in the background. This way, you can continue with other tasks while the solution is being computed. You can simply return when the execution is finished.

After the algorithm has finished, you can easily retrieve the solution for your QUBO. This solution will be a binary vector, indicating the settings of the variables.

# After the execution of your algorithm has finished, retrieve your solution
solution = lunaSolve.solution.get(

Alternatively, we also provide the possibility to run QAOA via Fire Opal. Fire Opal is a service from Q-CTRL that allows anyone to easily run their most valuable quantum applications by abstracting hardware, automatically reducing error, and boosting algorithmic success on quantum computers in the NISQ era and beyond. Applying these techniques to QAOA significantly increases performance and the likelihood of getting the right result on real hardware.

# Solve the QUBO using Fire Opal's QAOA and the least busy backend from IBM
job_fireopal = lunaSolve.solution.create(,
            "backend": "least_busy",
            "api_key": "<Fire Opal Key>",
            # If you are a member of multiple organizations at Q-CTRL, specify your organization here
            "organization_slug": "<Organization Slug>"

# After the execution of your algorithm has finished, retrieve your solution
solution_fireopal = lunaSolve.solution.get(

If you do not yet have an account with Fire Opal and would like to use this service, please contact us here.

Was this page helpful?