Solve the Market Split problem with Kipu Quantum's Iskay Quantum Optimizer
De Seitn is no ned ibersetzt worn. Sie schaung de englische Originalversion o.
Qiskit Functions are an experimental feature available only to IBM Quantum® Premium Plan, Flex Plan, and On-Prem (via IBM Quantum Platform API) Plan users. They are in preview release status and subject to change.
Usage estimate: 20 seconds on a Heron r2 processor. (NOTE: This is an estimate only. Your runtime might vary.)
Background
This tutorial demonstrates how to solve the Market Split problem using Kipu Quantum's Iskay quantum optimizer [1]. The Market Split problem represents a real-world resource allocation challenge where markets must be partitioned into balanced sales regions to meet exact demand targets.
The Market Split challenge
The Market Split problem presents a deceptively simple yet computationally formidable challenge in resource allocation. Consider a company with products being sold across different markets, where each market purchases a specific bundle of products (represented by the columns of matrix ). The business objective is to partition these markets into two balanced sales regions such that each region receives exactly half the total demand for every product.
Mathematical formulation:
We seek a binary assignment vector , where:
- assigns market to Region A
- assigns market to Region B
- The constraint must be satisfied, where represents the target sales (typically half the total demand per product)
Cost function:
To solve this problem, we minimize the squared constraint violation:
where:
- represents the sales of product in market
- is the binary assignment of market
- is the target sales for product in each region
- The cost equals zero precisely when all constraints are satisfied
Each term in the sum represents the squared deviation from the target sales for a particular product. When we expand this cost function, we get:
Since is a constant, minimizing is equivalent to minimizing the quadratic function , which is exactly a QUBO (Quadratic Unconstrained Binary Optimization) problem.
Computational complexity:
Despite its straightforward business interpretation, this problem exhibits remarkable computational intractability:
- Small-scale failure: Conventional Mixed Integer Programming solvers fail on instances with as few as seven products under a timeout of one hour [4]
- Exponential growth: The solution space grows exponentially ( possible assignments), making brute force approaches infeasible
This severe computational barrier, combined with its practical relevance to territory planning and resource allocation, makes the Market Split problem an ideal benchmark for quantum optimization algorithms [4].
What makes Iskay's approach unique?
The Iskay optimizer uses the bf-DCQO (bias-field digitized counterdiabatic quantum optimization) algorithm [1], which represents a significant advancement in quantum optimization:
Circuit efficiency: The bf-DCQO algorithm achieves remarkable gate reduction [1]:
- Up to 10 times fewer entangling gates than Digital Quantum Annealing (DQA)
- Significantly shallower circuits enable:
- Less error accumulation during quantum execution
- Ability to tackle larger problems on current quantum hardware
- No need for error mitigation techniques
Non-variational design: Unlike variational algorithms requiring approximately 100 iterations, bf-DCQO typically needs only approximately 10 iterations [1]. This is achieved through:
- Intelligent bias-field calculations from measured state distributions
- Starting each iteration from an energy state near the previous solution
- Integrated classical post-processing with local search
Counterdiabatic protocols: The algorithm incorporates counterdiabatic terms that suppress unwanted quantum excitations during short evolution times, enabling the system to remain near the ground state even with rapid transitions [1].
Requirements
Before starting this tutorial, ensure that you have the following installed:
- Qiskit IBM Runtime (
pip install qiskit-ibm-runtime) - Qiskit Functions (
pip install qiskit-ibm-catalog) - NumPy (
pip install numpy) - Requests (
pip install requests) - Opt Mapper Qiskit addon (
pip install qiskit-addon-opt-mapper)
You will also need to get access to the Iskay Quantum Optimizer function from the Qiskit Functions Catalog.
Setup
First, import all required packages for this tutorial.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit-addon-opt-mapper qiskit-ibm-catalog requests
import os
import tempfile
import time
from typing import Tuple, Optional
import numpy as np
import requests
from qiskit_ibm_catalog import QiskitFunctionsCatalog
from qiskit_addon_opt_mapper import OptimizationProblem
from qiskit_addon_opt_mapper.converters import OptimizationProblemToQubo
print("All required libraries imported successfully")
Configure IBM Quantum credentials
Define your IBM Quantum® Platform credentials. You will need:
- API Token: Your 44-character API key from IBM Quantum Platform
- Instance CRN: Your IBM Cloud® instance identifier
token = "<YOUR_API_KEY>"
instance = "<YOUR_INSTANCE_CRN>"
Step 1: Map classical inputs to a quantum problem
We begin by mapping our classical problem to a quantum-compatible representation. This step involves:
- Connecting to the Iskay Quantum Optimizer
- Loading and formulating the Market Split problem
- Understanding the bf-DCQO algorithm that will solve it
Connect to Iskay Quantum Optimizer
We begin by establishing a connection to the Qiskit Functions Catalog and loading the Iskay Quantum Optimizer. The Iskay Optimizer is a quantum function provided by Kipu Quantum that implements the bf-DCQO algorithm for solving optimization problems on quantum hardware.
catalog = QiskitFunctionsCatalog(token=token, instance=instance)
iskay_solver = catalog.load("kipu-quantum/iskay-quantum-optimizer")
print("Iskay optimizer loaded successfully")
print("Ready to solve optimization problems using bf-DCQO algorithm")
Load and formulate the problem
Understand the problem data format
Problem instances from QOBLIB (Quantum Optimization Benchmarking Library) [2] are stored in a simple text format. Let's examine the actual content of our target instance ms_03_200_177.dat:
3 20
60 92 161 53 97 2 75 81 6 139 132 45 108 112 181 93 152 200 164 51 1002
176 196 41 143 2 88 0 79 10 71 75 148 82 135 34 187 33 155 58 46 879
68 68 179 173 127 163 48 49 99 78 44 52 173 131 73 198 84 109 180 95 1040
Format structure:
-
First line:
3 203= number of products (constraints/rows in matrix )20= number of markets (variables/columns in matrix )
-
Next 3 lines: Coefficient matrix and target vector
- Each line has 21 numbers: first 20 are row coefficients, last is the target
- Line 2:
60 92 161 ... 51 | 1002- First 20 numbers: How much of Product 1 each of the 20 markets sells
- Last number (1002): Target sales for Product 1 in one region
- Line 3:
176 196 41 ... 46 | 879- Product 2 sales per market and target (879)
- Line 4:
68 68 179 ... 95 | 1040- Product 3 sales per market and target (1040)
Business interpretation:
- Market 0 sells: 60 units of Product 1, 176 units of Product 2, 68 units of Product 3
- Market 1 sells: 92 units of Product 1, 196 units of Product 2, 68 units of Product 3
- And so on for all 20 markets...
- Goal: Split these 20 markets into two regions where each region gets exactly 1002 units of Product 1, 879 units of Product 2, and 1040 units of Product 3
QUBO transformation
From constraints to QUBO: the mathematical transformation
The power of quantum optimization lies in transforming constrained problems into unconstrained quadratic forms [4]. For the Market Split problem, we convert the equality constraints
where , into a QUBO by penalizing constraint violations.
The penalty method: Since we need to hold exactly, we minimize the squared violation:
This equals zero precisely when all constraints are satisfied. Expanding algebraically:
QUBO objective: Since is constant, our optimization becomes:
Key insight: This transformation is exact, not approximate. Equality constraints naturally square into quadratic form without requiring auxiliary variables or penalty parameters - making this formulation mathematically elegant and computationally efficient for quantum solvers [4]. We'll use the OptimizationProblem class to define our constrained problem, then convert it to QUBO format using OptimizationProblemToQubo, both from the qiskit_addon_opt_mapper package. This automatically handles the penalty-based transformation.
Implement data loading and QUBO conversion functions
We now define three utility functions:
parse_marketsplit_dat()- Parses the.datfile format and extracts matrices andfetch_marketsplit_data()- Downloads problem instances directly from the QOBLIB repository
def parse_marketsplit_dat(filename: str) -> Tuple[np.ndarray, np.ndarray]:
"""
Parse a market split problem from a .dat file format.
Parameters
----------
filename : str
Path to the .dat file containing the market split problem data.
Returns
-------
A : np.ndarray
Coefficient matrix of shape (m, n) where m is the number of products
and n is the number of markets.
b : np.ndarray
Target vector of shape (m,) containing the target sales per product.
"""
with open(filename, "r", encoding="utf-8") as f:
lines = [
line.strip()
for line in f
if line.strip() and not line.startswith("#")
]
if not lines:
raise ValueError("Empty or invalid .dat file")
# First line: m n (number of products and markets)
m, n = map(int, lines[0].split())
# Next m lines: each row of A followed by corresponding element of b
A, b = [], []
for i in range(1, m + 1):
values = list(map(int, lines[i].split()))
A.append(values[:-1]) # First n values: product sales per market
b.append(values[-1]) # Last value: target sales for this product
return np.array(A, dtype=np.int32), np.array(b, dtype=np.int32)
def fetch_marketsplit_data(
instance_name: str = "ms_03_200_177.dat",
) -> Tuple[Optional[np.ndarray], Optional[np.ndarray]]:
"""
Fetch market split data directly from the QOBLIB repository.
Parameters
----------
instance_name : str
Name of the .dat file to fetch (default: "ms_03_200_177.dat").
Returns
-------
A : np.ndarray or None
Coefficient matrix if successful, None if failed.
b : np.ndarray or None
Target vector if successful, None if failed.
"""
url = f"https://git.zib.de/qopt/qoblib-quantum-optimization-benchmarking-library/-/raw/main/01-marketsplit/instances/{instance_name}"
try:
response = requests.get(url, timeout=30)
response.raise_for_status()
with tempfile.NamedTemporaryFile(
mode="w", suffix=".dat", delete=False, encoding="utf-8"
) as f:
f.write(response.text)
temp_path = f.name
try:
return parse_marketsplit_dat(temp_path)
finally:
os.unlink(temp_path)
except Exception as e:
print(f"Error: {e}")
return None, None
Load the problem instance
Now we load the specific problem instance ms_03_200_177.dat from QOBLIB [2]. This instance has:
- 3 products (constraints)
- 20 markets (binary decision variables)
- Over 1 million possible market assignments to explore ()
# Load the problem instance
instance_name = "ms_03_200_177.dat"
A, b = fetch_marketsplit_data(instance_name=instance_name)
if A is not None:
print("Successfully loaded problem instance from QOBLIB")
print("\nProblem Instance Analysis:")
print("=" * 50)
print(f"Coefficient Matrix A: {A.shape[0]} × {A.shape[1]}")
print(f" → {A.shape[0]} products (constraints)")
print(f" → {A.shape[1]} markets (decision variables)")
print(f"Target Vector b: {b}")
print(" → Target sales per product for each region")
print(
f"Solution Space: 2^{A.shape[1]} = {2**A.shape[1]:,} possible assignments"
)
Convert to QUBO format
We now transform the constrained optimization problem into QUBO format:
# Create optimization problem
ms = OptimizationProblem(instance_name.replace(".dat", ""))
# Add binary variables (one for each market)
ms.binary_var_list(A.shape[1])
# Add equality constraints (one for each product)
for idx, rhs in enumerate(b):
ms.linear_constraint(A[idx, :], sense="==", rhs=rhs)
# Convert to QUBO with penalty parameter
qubo = OptimizationProblemToQubo(penalty=1).convert(ms)
print("QUBO Conversion Complete:")
print("=" * 50)
print(f"Number of variables: {qubo.get_num_vars()}")
print(f"Constant term: {qubo.objective.constant}")
print(f"Linear terms: {len(qubo.objective.linear.to_dict())}")
print(f"Quadratic terms: {len(qubo.objective.quadratic.to_dict())}")
Convert QUBO to Iskay format
Now we need to convert the QUBO object into the dictionary format required by Kipu Quantum's Iskay Optimizer.
The problem and problem_type arguments encode an optimization problem of the form
where