Skip to content
Pasqal Documentation

Qubo embedding

import torch
from qubosolver.config import DeviceType, EmbeddingConfig, SolverConfig
from qubosolver.solver import QUBOInstance, QuboSolver
import matplotlib.pyplot as plt
plt.rcParams["animation.html"] = "jshtml"
%matplotlib inline

This tutorial aims to show small code snippet on how to use the different embedding methods (blade, custom, greedy) as well as how to parametrize the algorithms through the SolverConfig according to a given QUBO matrix.

# import QUBO matrix manually
coefficients = torch.load("qubo_size_15.pt", weights_only=True)
instance = QUBOInstance(coefficients)
config = SolverConfig(use_quantum=True)
config.print_specs()
solver = QuboSolver(instance, config)
geometry = solver.embedding()
geometry.register.draw()

Following previous workflow, we can reiterate using a more fined parametrization of the SolverConfig for the blade embedding method.

Here is a code snippet of an arbitrary parametrization of BLaDE using multiple layers of nn-dimension and a number of steps per round (i.e. number of iteration per layer):

blade_settings = EmbeddingConfig(embedding_method="blade", blade_dimensions=[5 ,4, 3, 2], blade_steps_per_round=300)
blade_config = SolverConfig.from_kwargs(
use_quantum=True,
device=DeviceType.ANALOG_DEVICE,
embedding=blade_settings,
)
solver = QuboSolver(instance, blade_config)
geometry = solver.embedding()
geometry.register.draw()

We do the same using the greedy embedding method, using a triangular lattice layout on a DigitalAnalogDevice with a number of traps at least equal to the number of variables in the QUBO:

greedy_settings = EmbeddingConfig(embedding_method="greedy", layout_greedy_embedder="triangular", traps=instance.size)
greedy_config = SolverConfig.from_kwargs(
use_quantum=True,
device=DeviceType.ANALOG_DEVICE,
embedding=greedy_settings,
)
solver = QuboSolver(instance, greedy_config)
geometry = solver.embedding()
geometry.register.draw()

If one desires to develop his own embedding method, a subclass of qubosolver.pipeline.embedder.BaseEmbedder should be implemented with a mandatory embed method.

The embed method def embed(self) -> qubosolver.pipeline.targets.Register specify how the problem is mapped into a register of qubits when running using a quantum device. Let us show a simple example where each variable ii is mapped into a qubit lying on a horizontal line (with coordinates [i,0][i, 0]).

import typing
from qubosolver.pipeline.embedder import BaseEmbedder
from qubosolver.pipeline.targets import Register as TargetRegister
from qubosolver.config import SolverConfig
from pulser.register import Register as PulserRegister
class FixedEmbedder(BaseEmbedder):
@typing.no_type_check
def embed(self) -> TargetRegister:
qubits = {f"q{i}": (i,0) for i in range(self.instance.coefficients.shape[0])}
register = PulserRegister(qubits)
return TargetRegister(self.config.backend_config.device, register)
custom_config = SolverConfig.from_kwargs(
use_quantum=True,
embedding_method=FixedEmbedder,
)
solver = QuboSolver(instance, custom_config)
geometry = solver.embedding()
geometry.register.draw()
from qubosolver.solver import QUBOInstance, QuboSolver
from qubosolver.config import SolverConfig, EmbeddingConfig, BackendConfig
from qoolqit._solvers.types import DeviceType
import torch
Q = torch.tensor([
[-4.0, 1.0, 2.0, 1.5, 2.3, 0.9, 1.8, 2.7, 1.2],
[ 1.0,-3.2, 1.7, 2.1, 0.8, 1.9, 2.2, 1.1, 1.6],
[ 2.0, 1.7,-5.1, 0.7, 2.5, 1.3, 2.6, 1.4, 2.0],
[ 1.5, 2.1, 0.7,-2.7, 1.2, 2.4, 0.6, 1.8, 2.1],
[ 2.3, 0.8, 2.5, 1.2,-6.3, 1.0, 1.7, 2.8, 1.5],
[ 0.9, 1.9, 1.3, 2.4, 1.0,-4.5, 2.3, 1.6, 0.9],
[ 1.8, 2.2, 2.6, 0.6, 1.7, 2.3,-3.8, 1.2, 2.2],
[ 2.7, 1.1, 1.4, 1.8, 2.8, 1.6, 1.2,-5.9, 1.4],
[ 1.2, 1.6, 2.0, 2.1, 1.5, 0.9, 2.2, 1.4,-2.4],
], dtype=torch.float32)
instance = QUBOInstance(Q)
greedy_settings = EmbeddingConfig(
embedding_method="greedy",
layout_greedy_embedder="triangular", # or "square"
traps=instance.size + 6,
spacing=5.0,
draw_steps=True, # ← single toggle
animation_save_path="greedy_demo.gif", # ← optional file export
)
backend = BackendConfig(device=DeviceType.ANALOG_DEVICE)
cfg = SolverConfig.from_kwargs(
use_quantum=True,
embedding=greedy_settings,
device=backend.device,
)
solver = QuboSolver(instance, cfg)
geometry = solver.embedding() # → inline animation + optional mp4