Solving a QUBO problem easily
Solving a QUBO problem is straightforward with qubo-solver. We can directly use the Solver class by providing an Instance with a given SolverConfig configuration.
SolverConfig specifies whether to use a classical approach or a quantum one. Note that SolverConfig comes with many options but the default ones can be used straightforwardly.
We have however more advanced tutorials on the quantum-related components to dive deeper into these advanced concepts.
Solving with a quantum approach
Section titled “Solving with a quantum approach”To use a quantum approach, several choices have to be made regarding the configuration, explained in more details in the Solving QUBOs section of the documentation (external).
One main decision is about the backend (external), that is how we choose to perform quantum runs. We can decide to either perform our on emulators (locally, or remotely) or using a real quantum processing unit (QPU). Our QPU, based on the Rydberg Analog Model, is accessible remotely.
Available backend types and devices
Section titled “Available backend types and devices”The supported backends are available via qoolqit (external), a Python package designed for algorithm development in the Rydberg Analog Model.
The backends can be divided into 3 main categories:
- Local emulators (external)
- Remote emulators (external), which can be accessed via
pasqal_cloud(external) - A remote QPU, such as Fresnel (external)
A backend will use device specifications to perform quantum computations. The list of supported devices can be found in the QoolQit devices documentation (external).
Running locally with an emulator
Section titled “Running locally with an emulator”We can perform quantum simulations locally via an emulator.
from __future__ import annotations
from qubosolver import ( Instance, LocalEmulator, QuantumSolvingConfig, Solver, SolverConfig, analysis, matrix,)
Q = matrix.tensor( [ [-0.2, 0.0, 1.0], [0.0, -1.0, 1.5], [1.0, 1.5, -0.1], ])instance = Instance(Q)
# Create a SolverConfig to use a quantum backend.quantum_config = QuantumSolvingConfig(backend=LocalEmulator())config = SolverConfig(solving=quantum_config)
solver = Solver(instance, config)solution = solver.solve()
print(analysis.to_dataframe([solution]))labels bitstrings costs counts probs 0 0 110 -0.2 38.0 0.038 1 0 100 -0.2 156.0 0.156 2 0 000 0.0 117.0 0.117 3 0 010 0.0 339.0 0.339 4 0 001 0.0 350.0 0.350
Running with a remote connection
Section titled “Running with a remote connection”We can decide to perform our runs remotely via pasqal_cloud (external).
To do so, we have to provide several information after setting up an account (external).
On a real QPU
Section titled “On a real QPU”The code above can be modified to solve the QUBO instance using our real QPU remotely as follows (run only with your pasqal_cloud information):
import qoolqitfrom pasqal_cloud import PasqalCloudConnectionfrom qoolqit.execution import QPU
from qubosolver import ( Instance, QuantumSolvingConfig, Solver, SolverConfig, analysis, matrix,)
# Replace with your username, project id and password on the Pasqal Cloud.USERNAME = "#TO_PROVIDE"PROJECT_ID = "#TO_PROVIDE"PASSWORD = None
Q = matrix.tensor( [ [-0.2, 0.0, 1.0], [0.0, -1.0, 1.5], [1.0, 1.5, -0.1], ])instance = Instance(Q)
if PASSWORD is not None: # Setup connection connection = PasqalCloudConnection( username=USERNAME, password=PASSWORD, project_id=PROJECT_ID, ) # Get available devices print(f"Available devices: {connection.fetch_available_devices()}") # Choose a device, and use a quantum backend device = qoolqit.Device.from_connection(connection, "FRESNEL_CAN1") qpu_backend = QPU(connection=connection, num_shots=1000)else: # Use a mock local connection for the tutorial from qubosolver import RemoteEmulator from qubosolver.utils._local_connection import LocalConnection
connection = LocalConnection() device = qoolqit.AnalogDevice() qpu_backend = RemoteEmulator(connection=connection)
quantum_config = QuantumSolvingConfig(device=device, backend=qpu_backend)
config = SolverConfig(solving=quantum_config)solver = Solver(instance, config)solution = solver.solve()
print(analysis.to_dataframe([solution]))labels bitstrings costs counts probs 0 0 110 -0.2 470.0 0.470 1 0 100 -0.2 53.0 0.053 2 0 001 0.0 282.0 0.282 3 0 000 0.0 148.0 0.148 4 0 010 0.0 47.0 0.047
On a remote emulators
Section titled “On a remote emulators”Emulators are also available remotely via pasqal_cloud:
from pasqal_cloud import PasqalCloudConnection
from qubosolver import ( Instance, QuantumSolvingConfig, RemoteEmulator, Solver, SolverConfig, analysis, matrix,)
# Replace with your username, project id and password on the Pasqal Cloud.USERNAME = "#TO_PROVIDE"PROJECT_ID = "#TO_PROVIDE"PASSWORD = None
Q = matrix.tensor( [ [-0.2, 0.0, 1.0], [0.0, -1.0, 1.5], [1.0, 1.5, -0.1], ])instance = Instance(Q)
if PASSWORD is not None: # Setup connection connection = PasqalCloudConnection( username=USERNAME, password=PASSWORD, project_id=PROJECT_ID, )else: # Use a mock local connection for tutorial from qubosolver.utils._local_connection import LocalConnection
connection = LocalConnection()
# Use a remote emulator backendremote_emulator_backend = RemoteEmulator(connection=connection)
quantum_config = QuantumSolvingConfig(device=device, backend=remote_emulator_backend)config = SolverConfig(solving=quantum_config)solver = Solver(instance, config)solution = solver.solve()
print(analysis.to_dataframe([solution]))labels bitstrings costs counts probs 0 0 110 -0.2 465.0 0.465 1 0 100 -0.2 62.0 0.062 2 0 010 0.0 35.0 0.035 3 0 001 0.0 276.0 0.276 4 0 000 0.0 162.0 0.162
Solving with a classical approach
Section titled “Solving with a classical approach”We show below an example of solving a QUBO using Tabu search. More information on classical approaches can be found in the Classical solvers section of the documentation (external).
from qubosolver import ( ClassicalSolvingConfig, Instance, Solver, SolverConfig, analysis, matrix,)
Q = matrix.tensor( [ [-0.2, 0.0, 1.0], [0.0, -1.0, 1.5], [1.0, 1.5, -0.1], ])instance = Instance(Q)
# Create a SolverConfig with a classical solver.classical_config = ClassicalSolvingConfig( algorithm="tabu_search", time_limit=10.0,)config = SolverConfig(solving=classical_config)
solver = Solver(instance, config)solution = solver.solve()
print(analysis.to_dataframe([solution]))The examples above use the Object API (Solver). Continue to the next tutorial, Using the functional API, for a lower-level, more flexible way of achieving the same results.
