Skip to main content
Fire Opal by Q-CTRL includes a built-in Quantum Approximate Optimization Algorithm (QAOA) solver that takes advantage of IonQ’s native all-to-all qubit connectivity to tackle dense optimization problems with greater accuracy. This guide walks through solving a Maximum Cut (Max-Cut) problem on IonQ hardware using the IonQ Python SDK with the ionq-qctrl extension.

What is Max-Cut?

Max-Cut is a combinatorial optimization problem: given a graph, partition its nodes into two groups to maximize the number of edges crossing the partition. For non-planar graphs there is no known polynomial-time classical solution, making it a strong candidate for quantum optimization.

Requirements

  • An IonQ Quantum Cloud account and API key stored as IONQ_API_KEY
  • A Q-CTRL account for Fire Opal with an API key stored as FIREOPAL_API_KEY
  • The ionq and ionq-qctrl Python packages

1. Imports and setup

import os

import networkx as nx
import matplotlib.pyplot as plt
from ionq.client import Client
from ionq import Backend
from ionq_qctrl.workloads import QctrlQaoa
Create a client and select a backend. Client() reads IONQ_API_KEY from your environment automatically:
client = Client()
backend = Backend(name="simulator", client=client)
To target a QPU instead of the simulator, pass name="qpu.forte-enterprise-1" (or another available system). Check device availability at status.ionq.co.
Read your Fire Opal API key from the environment. IonQ forwards this to Q-CTRL as part of the job’s external settings:
qctrl_api_credentials = os.environ.get("FIREOPAL_API_KEY")

2. Define the problem graph

Create a random graph to use as the Max-Cut input and visualize it:
graph = nx.gnm_random_graph(n=3, m=3)
nx.draw(graph, with_labels=True)
plt.show()
nx.gnm_random_graph(n, m) produces a random graph with n nodes and m edges. Swap in any networkx graph here — weighted graphs are also supported.

3. Build and submit the QAOA workload

Construct a QctrlQaoa workload, specifying "maxcut" as the problem type and passing the graph as the problem definition:
qaoa = QctrlQaoa(
    problem_type="maxcut",
    problem=graph,
    api_credentials=qctrl_api_credentials,
)
Submit the workload to IonQ. Fire Opal runs multiple consecutive circuit executions internally to optimize the QAOA parameters, so queue time may vary:
job = backend.run(
    qaoa,
    name="Q-CTRL QAOA parent job",
)

print("Submitted job id:", job.id)

4. Retrieve results

Call job.results() to wait for completion and fetch the output. The returned object contains the optimizer’s findings:
result = job.results()

print("processing_status:", result.processing_status)
print("optimal_cost:",      result.optimal_cost)
print("optimal_bitstring:", result.optimal_bitstring)
FieldDescription
processing_statusFinal status of the Fire Opal optimization run
optimal_costBest (lowest) cost value found across all QAOA iterations
optimal_bitstringThe node partition corresponding to the best cut found
The optimal_bitstring encodes which partition each node belongs to: a 0 or 1 per node, where nodes with different values are on opposite sides of the cut.

Next steps

For a deeper look at how the solver works and how to use it with Q-CTRL’s Fire Opal, see the Fire Opal QAOA Solver documentation.