주 콘텐츠로 건너뛰기
이 프로젝트는 베타 단계입니다. 버그를 발견하셨나요? GitHub 이슈 만들기. 질문이나 아이디어가 있으신가요? Discussions에서 질문하기 — 피드백을 기다립니다!
이 페이지의 번역 품질은 어떻습니까?

SQOA Solver - JIJ의 Qiskit Function

API 레퍼런스를 참조하세요.

참고

Qiskit Functions는 IBM Quantum® Premium Plan, Flex Plan, On-Prem(IBM Quantum Platform API를 통한) Plan 사용자만 사용할 수 있는 실험적 기능입니다. 미리 보기 릴리스 상태이며 변경될 수 있습니다.

개요​

JIJ의 SQOA Solver를 사용하면 IBM® 양자 컴퓨터에서 대규모 조합 최적화 문제를 해결할 수 있습니다. 이 솔버는 양자 이완을 이용한 샘플링 기반 양자 최적화 알고리즘(Sampling-based Quantum Optimization Algorithm with Quantum Relaxation, SQOA-QR) [1]을 기반으로 합니다. 고전적 결정 변수와 큐비트를 일대일로 대응시키는 양자 알고리즘과 달리, SQOA Solver는 현재 양자 장치에서 사용할 수 있는 큐비트 수보다 더 많은 변수를 가진 최적화 문제를 처리할 수 있습니다. 또한 샘플링 기반 설계 덕분에 현재 양자 하드웨어의 물리적 노이즈에 덜 민감합니다. 이러한 특징들이 합쳐져 SQOA Solver는 양자 컴퓨팅의 현 단계에서 최적화 문제에 적합합니다.

이 솔버는 고전적 수학 공식으로 주어진 이차 비제약 이진 최적화(Quadratic Unconstrained Binary Optimization, QUBO) 문제를 처리하며, 고전적 공식을 양자 환경으로 자동 매핑합니다. 페널티 방법을 사용하여 제약 문제를 비제약 문제로 변환할 수도 있습니다.

다음 섹션에서는 솔버의 워크플로, 벤치마크 결과, 그리고 qiskit-addon-opt-mapper와 선택적으로 Open Mathematical prograMming eXchange(OMMX)로 문제를 모델링하는 종단 간 예제를 설명합니다. OMMX는 소프트웨어 도구 간 최적화 문제 교환을 단순화하는 개방형 데이터 형식이자 SDK입니다.

설명​

SQOA Solver는 양자 이완을 이용한 샘플링 기반 양자 최적화 알고리즘(SQOA-QR)을 구현하며, 그 앞뒤로 고전적 전처리와 후처리를 수행합니다. 이 섹션에서는 SQOA 프레임워크와 이것이 양자 근사 최적화 알고리즘(Quantum Approximate Optimization Algorithm, QAOA)과 어떻게 다른지 설명합니다.

다음 그림은 SQOA Solver 워크플로의 개략도입니다. 고전적 전처리에서 SQOA 샘플링, 후처리 및 로컬 탐색에 이르는 SQOA Solver 워크플로의 개략도

SQOA 프레임워크​

SQOA는 조합 최적화를 위한 샘플링 기반 프레임워크입니다 [1]. 이 프레임워크는 두 가지 기법을 결합합니다. 하나는 문제를 양자 이완으로 인코딩하는 양자 랜덤 액세스 최적화(Quantum Random Access Optimization, QRAO) [2]이고, 다른 하나는 양자 선택 배위 상호작용(quantum-selected configuration interaction, QSCI) [4]라고도 하는 샘플 기반 양자 대각화(sample-based quantum diagonalization, SQD) [3]로, 양자 컴퓨터는 비트열 샘플링에만 사용하고 저에너지 상태는 고전 컴퓨터에서 찾습니다. SQOA는 이 조합을 고정하되, 변수를 큐비트에 할당하는 방법이나 샘플을 생성하는 회로 같은 세부 사항은 각 구현에 맡긴다는 의미에서 프레임워크입니다.

  • QRAO를 이용한 양자 이완. QAOA 및 기타 Ising 기반 접근 방식은 각 이진 변수를 해당 큐비트의 ZZ 연산자로 표현합니다. QRAO는 XX와 YY 연산자도 사용합니다. (3,1) 양자 랜덤 액세스 코드(QRAC)에서는 최대 세 개의 이진 변수가 하나의 큐비트를 공유하며, 각 변수는 서로 다른 Pauli 연산자로 표현됩니다.

    그러면 QUBO는 Ising 해밀토니언보다 적은 큐비트가 필요한 이완된 해밀토니언이 됩니다. QUBO에서 상호작용하는 변수는 서로 다른 큐비트에 배치해야 합니다. 같은 큐비트를 공유하면 Pauli 연산자의 곱이 그 큐비트의 단일 연산자로 줄어들고(예: XY=iZXY = iZ), 이완된 해밀토니언이 더 이상 그 상호작용을 나타내지 못하기 때문입니다.

    따라서 변수를 큐비트에 할당하는 방식이 큐비트 수와 이완의 품질을 모두 결정하며, SQOA Solver는 전처리 단계에서 이 할당을 설계합니다.

  • 샘플 기반 양자 대각화(SQD). 양자 컴퓨터는 먼저 이완된 해밀토니언의 저에너지 상태와 겹치는 양자 상태를 준비한 다음 그 상태에서 비트열을 샘플링합니다. 고전 컴퓨터는 이완된 해밀토니언을 샘플링된 비트열이 span하는 부분 공간에 사영하고 대각화하여 바닥 상태를 근사합니다.

    이완된 해밀토니언은 비대각 행렬이므로, 대각화 과정에서 샘플링된 비트열이 중첩으로 결합됩니다. 대각 Ising 해밀토니언에서는 모든 비트열이 이미 고유 상태이므로, 대각화는 가장 좋은 샘플을 선택하는 데 그칠 것입니다. 같은 접근 방식이 양자 화학의 대규모 문제에도 적용되었습니다.

SQD로 얻은 근사 바닥 상태는 원래 문제의 고전적 해에 직접 대응하지 않으므로, 이 상태로부터 고전적 해를 디코딩해야 합니다. 이 상태는 고전 컴퓨터에서 계산되므로, 라운딩이라고 하는 디코딩은 고전적 후처리입니다. SQOA Solver는 휴리스틱하게 더 나은 고전적 해를 얻도록 설계된 디코딩 기법을 사용합니다.

다음 표는 같은 종류의 문제에 대한 일반적인 변분 접근 방식인 QAOA와 SQOA를 비교한 것입니다.

 QAOASQOA
이진 변수 nn개에 필요한 큐비트nn하나의 큐비트가 최대 세 개의 변수를 담습니다. 정확한 수는 문제 구조에 따라 다릅니다
QPU 사용 방식고전적 최적화 루프 안에서 매개변수화된 회로의 에너지를 반복적으로 추정합니다비트열만 샘플링합니다. QPU에서 회로 매개변수를 훈련하지 않습니다
샘플에서 해까지측정된 비트열 중 가장 좋은 것을 선택합니다샘플링된 부분 공간에서 이완된 해밀토니언을 고전 컴퓨터로 대각화하고 결과 상태를 라운딩합니다

SQOA Solver는 SQOA-QR 주변에 고전적 처리를 추가합니다. 전처리에서는 최적값을 미리 결정할 수 있는 변수를 고정하고 변수의 큐비트 할당을 설계합니다. 후처리에서는 로컬 탐색으로 라운딩된 해를 개선하며, postprocessing_level=0으로 이를 끌 수 있습니다.

벤치마크​

면책 조항

성능은 문제 인스턴스와 이후 처리 단계 모두에 따라 달라질 수 있습니다. 경우에 따라 고전적 샘플과 양자로 생성된 샘플은 동등한 후처리 후에 비슷한 최종 해 품질을 달성할 수 있습니다. 따라서 평가는 전체 최적화 워크플로를 고려해야 합니다.

다음 벤치마크 지표는 선택된 문제 크기와 구조에 걸친 해 품질, 큐비트 압축, 실행 시간에 대한 일반적인 지표를 제공합니다. 표에는 Quantum Optimization Benchmarking Library(QOBLIB)의 최대 독립 집합 인스턴스 일부와 두 개의 3-정규 MaxCut 인스턴스가 나열되어 있습니다. ommx-quantum-benchmarks 패키지를 사용하면 QOBLIB 인스턴스를 최적해와 함께 ommx.v1.Instance 객체로 불러올 수 있습니다.

각 인스턴스는 IBM Heron r2 프로세서에서 10회 실행되었습니다. Number of qubits는 전처리와 QRAC 인코딩 후 하드웨어에서 실제로 사용된 큐비트 수입니다. 압축 비율은 인스턴스에 따라 다릅니다. Approximation ratio(AR)는 10회 실행에서 찾은 최상의 해의 품질을 나타냅니다.

AR=CbestCopt,\mathrm{AR} = \frac{C_{\textrm{best}}}{C_{\textrm{opt}}},

여기서 CbestC_{\textrm{best}}는 찾은 최상의 목적 함수 값이고 CoptC_{\textrm{opt}}는 알려진 최적 목적 함수 값입니다. 모든 인스턴스는 최적값이 양수인 최대화 문제이므로 AR은 최대 100%이며, Approximation ratio 열의 100%는 솔버가 최적해를 찾았음을 나타냅니다. Total time은 실행당 평균 QPU 및 CPU 시간의 합입니다. QPU time은 실행당 평균 IBM Quantum Compute 사용량입니다.

인스턴스변수 수큐비트 수근사 비율총 시간(초)QPU 시간(초)
maxcut_384_nodes38412998.5%62.112.0
gen200_p0-9_4420067100%38.012.0
es60fst0218642100%24.712.0
es60fst0416229100%17.912.0
maxcut_150_nodes15051100%23.112.0
sloane_1dc_1281283793.8%19.112.0
sloane_2dc_1281288100%12.311.5
C125-912543100%22.312.0
es60fst0112312100%13.612.0
es60fst0311326100%14.912.0
sloane_1dc_646416100%13.411.9
chesapeake3913100%13.112.0
football356100%12.512.0
karate342100%6.26.0
ibm323211100%12.912.0
farm174100%8.58.0

시작하기​

이 Qiskit Function의 액세스 정보는 Qiskit Functions Catalog에서 확인하세요.

이 섹션에서는 인증하고 함수를 불러오는 방법과, qiskit-addon-opt-mapper의 OptimizationProblem을 사용하여 SQOA Solver가 허용하는 딕셔너리 형식으로 문제를 준비하는 방법을 보여 줍니다. 이어지는 예제에서는 함수를 실행하고 결과를 읽습니다.

함수 인증 및 불러오기​

먼저 IBM Quantum API 키로 인증합니다. (다음 코드는 이미 로컬 환경에 계정을 저장했다고 가정합니다.) 그런 다음 다음과 같이 카탈로그 클라이언트를 만듭니다.

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"jijmodeling": "jijmodeling", "networkx": "networkx", "ommx": "ommx", "qiskit_addon_opt_mapper": "qiskit-addon-opt-mapper", "qiskit_ibm_catalog": "qiskit-ibm-catalog"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")

# verify that you have access to the function
catalog.list()
[QiskitFunction(jij/sqoa-solver)]
solver = catalog.load("jij/sqoa-solver")

qiskit-addon-opt-mapper로 입력 준비하기​

이 가이드는 qiskit-addon-opt-mapper의 OptimizationProblem 클래스로 문제를 모델링합니다. SQOA Solver는 IBM 최적화 함수에서 사용하는 튜플 문자열 형식의 계수 딕셔너리로 QUBO 문제를 받으므로, 이 가이드의 모든 예제는 동일한 클라이언트 측 준비 패턴을 따릅니다.

  1. 모델 작성. OptimizationProblem을 만들고, 이진 결정 변수를 추가한 다음, 목적 함수와 제약 조건을 설정합니다.

  2. QUBO로 변환. OptimizationProblemToQubo로 문제를 변환합니다. 이 변환은 제약 조건을 페널티 항으로 목적 함수에 추가하고 동등한 비제약 최소화 문제를 반환합니다.

  3. 딕셔너리로 변환. QUBO를 다음 섹션에서 정의하는 to_problem_dict() 헬퍼 함수에 전달하고, 그 결과를 variable_type="binary"와 함께 problem으로 solver.run()에 전달합니다.

SQOA Solver는 딕셔너리 문제를 항상 최소화하며, 이는 OptimizationProblemToQubo가 반환하는 최소화 문제와 일치합니다. 따라서 최대화 문제의 경우 반환된 objective_value는 원래 목적 함수의 음수입니다. 결과를 원래 문제의 관점에서 읽으려면 예제와 같이 OptimizationProblem으로 반환된 할당을 평가하세요. 딕셔너리 형식에 대한 자세한 내용은 API 레퍼런스의 허용되는 문제 형식을 참조하세요.

# %pip install qiskit-addon-opt-mapper

다음 헬퍼 함수를 한 번 정의하고 모든 예제에서 재사용하세요. 이 함수는 OptimizationProblemToQubo가 반환한 QUBO를 딕셔너리 형식으로 변환합니다. 키는 QUBO의 변수 인덱스를 사용하므로, 결과의 솔루션 키 x_0, x_1 등은 해당 인덱스에 대응합니다. 반환된 솔루션이 모든 변수를 포함하도록, 계수가 0이더라도 모든 변수에 선형 항목이 지정됩니다.

from qiskit_addon_opt_mapper import OptimizationProblem
from qiskit_addon_opt_mapper.converters import OptimizationProblemToQubo

def to_problem_dict(qubo: OptimizationProblem) -> dict[str, float]:
"""Convert a QUBO from OptimizationProblemToQubo to the SQOA Solver dictionary format."""
objective = qubo.objective
payload = {"()": objective.constant}
# Keep every variable in the problem, even with a zero linear coefficient.
payload.update({f"({i},)": 0.0 for i in range(qubo.get_num_vars())})
for i, coefficient in objective.linear.to_dict().items():
payload[f"({i},)"] += coefficient
for (i, j), coefficient in objective.quadratic.to_dict().items():
# Fold a binary diagonal term x_i * x_i = x_i into the linear term.
key = f"({i},)" if i == j else f"({i}, {j})"
payload[key] = payload.get(key, 0.0) + coefficient
return {key: float(value) for key, value in payload.items()}

예제 1: 3-정규 그래프의 MaxCut​

MaxCut과 같은 많은 그래프 문제는 NP-hard이며 양자 최적화의 자연스러운 후보입니다. 이 예제를 실행하려면 추가 의존성으로 networkx를 설치하세요.

# %pip install networkx

1. 모델 작성​

그래프 G=(V,E)G = (V, E)의 각 정점에 이진 변수 xv∈{0,1}x_v \in \{0, 1\}를 할당하여 컷에서 그 정점이 속한 쪽을 나타냅니다. 간선의 양 끝점이 서로 다른 쪽에 있으면 그 간선이 잘리므로, 컷 크기는 다음과 같습니다.

Cut(x)=∑(u,v)∈E(xu+xv−2xuxv).\mathrm{Cut}(x) = \sum_{(u,v) \in E} \left(x_u + x_v - 2 x_u x_v\right).

이 목적 함수는 이미 제약 조건이 없는 QUBO이므로, OptimizationProblemToQubo는 최대화를 동등한 최소화로 바꾸기만 하고 변수는 그대로 유지합니다. qiskit_addon_opt_mapper.applications의 Maxcut 애플리케이션 클래스는 Maxcut(G).to_optimization_problem()으로 동일한 모델을 만듭니다.

import networkx as nx

G = nx.random_regular_graph(3, 40, seed=42)

linear = {v: 0 for v in G.nodes}
quadratic = {}
for u, v in G.edges:
linear[u] += 1
linear[v] += 1
quadratic[(u, v)] = -2

maxcut = OptimizationProblem("MaxCut")
maxcut.binary_var_list(G.number_of_nodes(), name="x")
maxcut.maximize(linear=linear, quadratic=quadratic)

2. 솔버 실행​

모델을 QUBO로 변환한 다음 딕셔너리로 변환하여 제출합니다. problem과 variable_type은 필수입니다. backend_name은 선택 사항입니다. 생략하거나 None이면, 함수가 인스턴스에서 사용할 수 있는 가장 한가한 운영 중인 QPU를 선택합니다.

options 딕셔너리는 shots, seed, session, postprocessing_level, job_tags를 받습니다. 설명과 기본값은 API 레퍼런스를 참조하세요.

qubo = OptimizationProblemToQubo().convert(maxcut)

job = solver.run(
problem=to_problem_dict(qubo),
variable_type="binary",
backend_name="ibm_fez",
options={
"shots": 4096,
"seed": 42,
},
)

3. 결과 가져오기​

job.result()는 네 개의 키가 있는 딕셔너리를 반환합니다.

  • solution은 x_i 키로 구성된 전체 변수 할당이며, 여기서 i는 변수 인덱스입니다(예: x_3).

  • objective_value와 feasible은 제출된 딕셔너리에서 평가한, 해당 할당의 목적 함수 값과 실행 가능 여부입니다.

  • metadata에는 solver_info와 resource_usage가 들어 있습니다.

QUBO는 MaxCut의 최소화 형태이므로 objective_value는 컷 크기의 음수입니다. 컷 크기를 직접 읽으려면 원래의 OptimizationProblem에서 할당을 평가하세요.

result = job.result()

x = [result["solution"][f"x_{i}"] for i in range(maxcut.get_num_vars())]
print(f"Cut value: {maxcut.objective.evaluate(x)}")
print(f"Nodes on side 1: {[v for v, value in enumerate(x) if value > 0.5]}")
Cut value: 55.0
Nodes on side 1: [5, 7, 9, 11, 14, 16, 17, 19, 21, 23, 24, 26, 30, 31, 33, 34, 36, 37, 38]

4. 리소스 사용량 확인​

result["metadata"]["resource_usage"]는 각 실행 단계에서 소요된 시간을 보고합니다. RUNNING: EXECUTING_QPU 이외의 단계는 사용 가능한 경우 해당 단계의 실제 경과 시간(초)인 CPU_TIME을 보고합니다.

RUNNING: EXECUTING_QPU 단계는 모든 작업에 대해 최종 사용량을 확인할 수 있는 경우, 해당 실행의 모든 Quantum Compute 작업의 QPU 사용량인 QPU_TIME을 보고합니다. 자세한 내용은 API 레퍼런스를 참조하세요.

for phase, metrics in result["metadata"]["resource_usage"].items():
line = f"{phase:36s}"
if "CPU_TIME" in metrics:
line += f" CPU {metrics['CPU_TIME']:8.1f} s"
if "QPU_TIME" in metrics:
line += f" QPU {metrics['QPU_TIME']:8.1f} s"
print(line)
RUNNING: MAPPING CPU 3.2 s
RUNNING: OPTIMIZING_FOR_HARDWARE CPU 5.0 s
RUNNING: WAITING_FOR_QPU CPU 1.1 s
RUNNING: EXECUTING_QPU QPU 3.0 s
RUNNING: POST_PROCESSING CPU 0.9 s

예제 2: 제약 문제를 QUBO로 변환하기​

SQOA Solver는 비제약 문제를 받습니다. 이 예제에서는 OptimizationProblemToQubo로 제약 문제를 QUBO로 변환하고 그 결과를 원래 문제의 변수로 다시 매핑하는 방법을 보여 줍니다.

selection = OptimizationProblem("ConstrainedExample")
selection.binary_var_list(2, name="x")
selection.maximize(linear={"x0": 1, "x1": 1})
selection.linear_constraint({"x0": 1, "x1": 1}, "<=", 1, name="at_most_one")

print(selection.prettyprint())
Problem name: ConstrainedExample

Maximize
x0 + x1

Subject to
Linear constraints (1)
x0 + x1 <= 1 'at_most_one'

Binary variables (2)
x0 x1

OptimizationProblemToQubo는 제약 조건을 페널티 항으로 목적 함수에 추가하고 문제를 최소화로 변환합니다. 적절한 페널티 가중치는 문제에 따라 다릅니다.

실행 후 interpret()는 QUBO 할당을 원래 문제의 변수로 다시 매핑합니다.

원래 문제에서 목적 함수와 실행 가능 여부를 평가하세요. 딕셔너리 문제에는 제약 조건이 없으므로, 결과의 feasible 필드는 변수 정의역만을 나타냅니다.

converter = OptimizationProblemToQubo(penalty=4.0)
qubo = converter.convert(selection)

job = solver.run(
problem=to_problem_dict(qubo),
variable_type="binary",
backend_name="ibm_fez",
)
result = job.result()

x_qubo = [result["solution"][f"x_{i}"] for i in range(qubo.get_num_vars())]
x = converter.interpret(x_qubo)
print("Objective:", selection.objective.evaluate(x))
print("Feasible:", selection.is_feasible(x))
print("x values:", x)
Objective: 1.0
Feasible: True
x values: [1. 0.]

예제 3: OMMX 인스턴스 제출하기​

SQOA Solver는 OMMX SDK의 ommx.v1.Instance도 받습니다. 이는 변수 이름, 첨자, 변환 메타데이터를 문제와 함께 보관합니다. 딕셔너리와 비교하여 OMMX 입력에는 다음과 같은 장점이 있습니다.

  • 결과에는 solver_info["ommx_solution"]에 표준 ommx.v1.Solution도 포함됩니다.

  • objective_value는 인스턴스의 의미에 따라 평가되므로, 최대화 문제의 목적 함수는 부호가 바뀌지 않습니다.

  • Instance.to_qubo()로 제자리에서 변환된 인스턴스의 경우, feasible은 원래 제약 조건을 기준으로 평가됩니다.

이 예제는 모델을 OMMX 인스턴스로 컴파일하는 수학적 최적화 모델러인 JijModeling으로 예제 1의 MaxCut 모델을 구축합니다. ommx 패키지도 함께 설치되는 JijModeling을 설치하세요.

# %pip install "jijmodeling~=2.8.0"

SQOA Solver는 OMMX 데이터를 표준 패딩된 Base64 문자열로 교환합니다. 이 변환을 위해 다음 헬퍼 함수를 정의하세요.

  • to_problem_payload()는 ommx.v1.Instance를 problem으로 전달하는 문자열로 직렬화합니다.

  • to_ommx_solution()은 결과에서 표준 ommx.v1.Solution을 디코딩합니다.

import base64

from ommx.v1 import Instance, Solution

def to_problem_payload(instance: Instance) -> str:
"""Serialize an OMMX instance into the `problem` string for SQOA Solver."""
return base64.b64encode(instance.to_bytes()).decode()

def to_ommx_solution(result: dict) -> Solution:
"""Decode the canonical OMMX solution from a SQOA Solver result."""
payload = result["metadata"]["solver_info"]["ommx_solution"]
return Solution.from_bytes(base64.b64decode(payload, validate=True))

1. JijModeling으로 모델 작성​

그래프 G=(V,E)G = (V, E)에 대한 MaxCut의 일반적인 스핀 공식은 각 정점에 sv∈{−1,+1}s_v \in \{-1, +1\}를 할당합니다. susv=−1s_u s_v = -1이면 간선이 잘리므로, 컷 크기는 다음과 같습니다.

Cut⁡(s)=∑(u,v)∈E1−susv2.\operatorname{Cut}(s) = \sum_{(u,v) \in E} \frac{1 - s_u s_v}{2}.

JijModeling은 네이티브 스핀 결정 변수를 제공하지 않으며, SQOA Solver는 이진 QUBO 변수를 받습니다. 따라서 bv∈{0,1}b_v \in \{0, 1\}를 선언하고 모델 안에서 스핀 값 표현식 sv=1−2bvs_v = 1 - 2b_v를 정의합니다. 이 표현식을 사용하면 목적 함수가 표준 스핀 형태로 유지되고 컴파일된 인스턴스는 이진 QUBO로 남습니다.

import jijmodeling as jm

@jm.Problem.define("MaxCut", sense=jm.ProblemSense.MAXIMIZE)
def maxcut_model(problem: jm.DecoratedProblem):
V = problem.Natural() # number of nodes
E = problem.Graph(dtype=V) # edge list
b = problem.BinaryVar(shape=(V,))
s = 1 - 2 * b # spin-valued expression

problem += jm.sum((1 - s[u] * s[v]) / 2 for u, v in E)

노트북에서 maxcut_model을 표시하면 다음 공식이 나타납니다.

Problem ⁣:MaxCutmax⁡∑⟨u,v⟩∈E1−(1−2⋅b)u⋅(1−2⋅b)v2whereDecision Variables:bi∈{0,1}a 1-dim array of binary decision variables∀i∈{0,…,V−1}Placeholders:Ei∈V×Va 1-dim array of placeholders with elements in V×V∀i∈{0,…,len_at(E,0)−1}V∈Na scalar placeholder in N\begin{array}{rl} \text{Problem}\colon &\text{MaxCut}\\ \displaystyle \max &\displaystyle \sum _{\left\langle u,v\right\rangle \in E}{\frac{1-{\left(1-2\cdot b\right)}_{u}\cdot {\left(1-2\cdot b\right)}_{v}}{2}}\\ &\\ \text{where}&\\ &\text{Decision Variables:}\\ &\qquad \begin{alignedat}{2}{b}_{i}&\in \left\{0,1\right\}&\qquad &\text{a }1\text{-dim array of }\text{binary}\text{ decision variables}\\ &\forall i\in \left\{0,\ldots ,V-1\right\}&&\\ \end{alignedat}\\ &\\ &\text{Placeholders:}\\ &\qquad \begin{alignedat}{2}{E}_{i}&\in V\times V&\qquad &\text{a }1\text{-dim array of placeholders with elements in }V\times V\\ &\forall i\in \left\{0,\ldots ,\mathop{\mathtt{len\_{}at}}\left(E,0\right)-1\right\}&&\\ &&&\\ V&\in \mathbb{N}&\qquad &\text{a scalar placeholder in }\mathbb{N}\\ \end{alignedat}\end{array}

2. 인스턴스 컴파일 및 솔버 실행​

예제 1의 그래프를 바인딩하여 ommx.v1.Instance를 컴파일하고 variable_type="binary"로 제출합니다. OMMX 인스턴스는 항상 이진 문제로 제출됩니다.

instance = maxcut_model.eval(
{"V": G.number_of_nodes(), "E": [list(edge) for edge in G.edges]}
)

job = solver.run(
problem=to_problem_payload(instance),
variable_type="binary",
backend_name="ibm_fez",
)

3. 결과 가져오기​

OMMX 입력의 경우 objective_value는 컷 크기이며, to_ommx_solution()은 표준 솔루션을 디코딩하여 변수 이름으로 할당을 읽을 수 있게 합니다.

result = job.result()
print(f"Cut value: {result['objective_value']}")

solution = to_ommx_solution(result)
b_values = solution.extract_decision_variables("b")
print(
f"Nodes on side 1: {sorted(v for (v,), value in b_values.items() if value > 0.5)}"
)
Cut value: 55.0
Nodes on side 1: [5, 7, 9, 11, 14, 16, 17, 19, 21, 23, 24, 26, 30, 31, 33, 34, 36, 37, 38]

지원 받기​

지원이 필요하면 info@j-ij.com으로 이메일을 보내세요.

다음 단계​

권장 사항
  • 이 양식을 작성하여 SQOA Solver 무료 체험을 요청하세요.
  • 이 Qiskit Function의 API 레퍼런스를 확인하세요.
  • 최대 독립 집합 문제 튜토리얼에서 종단 간 예제를 시도해 보세요.
  • qiskit-addon-opt-mapper로 최적화 문제를 모델링하는 방법을 알아보세요.
  • JijModeling과 OMMX로 최적화 문제를 모델링하고 교환하는 방법을 알아보세요.
  • SQOA 프레임워크에 대해 더 알아보려면 SQOA-QR 논문 [1]을 읽어 보세요.

참고 문헌​

[1] Matsuyama, H., & Yamashiro, Y. (2025). Sampling-based quantum optimization algorithm with quantum relaxation. 2025 IEEE International Conference on Quantum Computing and Engineering (QCE), 1, 2323–2333. DOI, arXiv:2504.12629

[2] Fuller, B., Hadfield, C., Glick, J. R., Imamichi, T., Itoko, T., Thompson, R. J., Jiao, Y., Kagele, M. M., Blom-Schieber, A. W., Raymond, R., et al. (2024). Approximate solutions of combinatorial problems via quantum relaxations. IEEE Transactions on Quantum Engineering, 5, 1–15. DOI, arXiv:2111.03167

[3] Robledo-Moreno, J., Motta, M., Haas, H., Javadi-Abhari, A., Jurcevic, P., Kirby, W., et al. (2025). Chemistry beyond the scale of exact diagonalization on a quantum-centric supercomputer. Science Advances, 11(25), eadu9991. DOI, arXiv:2405.05068

[4] Kanno, K., Kohda, M., Imai, R., Koh, S., Mitarai, K., Mizukami, W., & Nakagawa, Y. O. (2026). Quantum-selected configuration interaction: Classical diagonalization of Hamiltonians in subspaces selected by quantum computers. Physical Review Research, 8(2), 023268. DOI, arXiv:2302.11320