diff --git a/qsplit/adapters/ibm/__ibm_pce.py b/qsplit/adapters/ibm/__ibm_pce.py
new file mode 100644
index 0000000..e9ed1bb
--- /dev/null
+++ b/qsplit/adapters/ibm/__ibm_pce.py
@@ -0,0 +1,200 @@
+# Copyright (C) 2025 The QSplit Contributors.
+# See the 'CONTRIBUTORS' file at the top-level directory of this distribution.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+from itertools import combinations
+from math import comb
+
+import numpy as np
+import pandas as pd
+from qiskit import QuantumCircuit, generate_preset_pass_manager
+from qiskit.circuit.library import qaoa_ansatz
+from qiskit.passmanager import BasePassManager
+from qiskit.quantum_info import SparsePauliOp
+from qiskit_ibm_runtime import EstimatorV2
+from scipy.optimize import minimize
+
+from qsplit.adapters.ibm.util import get_variables_mapping, to_dataframe
+from qsplit.qubo import QUBO
+
+
+def ibm_solve(qubo: QUBO, backend) -> pd.DataFrame:
+ var_to_qubit, all_vars = get_variables_mapping(qubo)
+ pm = generate_preset_pass_manager(backend=backend, optimization_level=2)
+ quantum_results = __run_quantum_optimizer(var_to_qubit, all_vars, qubo, backend, pm, k=3)
+ return to_dataframe(quantum_results, qubo, var_to_qubit, all_vars)
+
+
+def __build_pce(pauli: str, node_list: list, n_qubits: int, k: int) -> list[SparsePauliOp]:
+ pauli_correlation_encoding = []
+ for idx, c in enumerate(combinations(range(n_qubits), k)):
+ if idx >= len(node_list):
+ break
+ paulis = ["I"] * n_qubits
+ for qubit_idx in c:
+ paulis[qubit_idx] = pauli
+ pauli_correlation_encoding.append(("".join(paulis)[::-1], 1.0))
+
+ hamiltonians = []
+ for p_str, weight in pauli_correlation_encoding:
+ hamiltonians.append(SparsePauliOp.from_list([(p_str, weight)]))
+ return hamiltonians
+
+
+def __pce_loss(
+ x: list[float],
+ ansatz: QuantumCircuit,
+ hamiltonians: list,
+ estimator,
+ J_prime: dict,
+ num_nodes: int,
+ num_qubits: int,
+) -> dict[str, float | dict]:
+ job = estimator.run([(ansatz, hamiltonians[0], x), (ansatz, hamiltonians[1], x), (ansatz, hamiltonians[2], x)])
+ result = job.result()
+
+ node_exp_map = {}
+ idx = 0
+ for r in result:
+ for ev in r.data.evs:
+ node_exp_map[idx] = ev
+ idx += 1
+
+ loss_val = 0
+ alpha = num_qubits
+
+ for (edge0, edge1), weight in J_prime.items():
+ loss_val += weight * np.tanh(alpha * node_exp_map[edge0]) * np.tanh(alpha * node_exp_map[edge1])
+
+ regulation_term = 0
+ for i in range(num_nodes):
+ regulation_term += np.tanh(alpha * node_exp_map[i]) ** 2
+ regulation_term = (regulation_term / num_nodes) ** 2
+
+ beta = 1 / 2
+ v = len(J_prime) / 2 + (num_nodes - 1) / 4
+ regulation_term = beta * v * regulation_term
+
+ loss_val += regulation_term
+
+ return {"loss": loss_val, "exp_map": node_exp_map}
+
+
+def __run_quantum_optimizer(
+ var_to_qubit, all_vars, qubo: QUBO, backend, pm: BasePassManager, k: int = 3
+) -> dict[int, int]:
+ n = len(all_vars)
+ Q = np.zeros((n, n))
+ row_indices = [var_to_qubit[r] for r in qubo.rows_idx]
+ col_indices = [var_to_qubit[c] for c in qubo.cols_idx]
+ Q[np.ix_(row_indices, col_indices)] = qubo.mat
+ J_prime = {}
+
+ u_idx, v_idx = np.triu_indices(n, k=1)
+ for u, v in zip(u_idx, v_idx):
+ if Q[u, v] != 0:
+ J_prime[(u, v)] = Q[u, v] / 4.0
+
+ diag_Q = np.diag(Q)
+ sum_rows_cols = np.sum(Q, axis=1) + np.sum(Q, axis=0) - 2 * diag_Q
+ h = -diag_Q / 2.0 - sum_rows_cols / 4.0
+
+ dummy_index = n
+ for u, val in enumerate(h):
+ if val != 0:
+ J_prime[(u, dummy_index)] = val
+
+ num_nodes = n + 1
+ q = k
+ while 3 * comb(q, k) < num_nodes:
+ q += 1
+ num_qubits = q
+
+ list_size = num_nodes // 3
+ remainder = num_nodes % 3
+ nodes = list(range(num_nodes))
+ split_1 = list_size + (1 if remainder > 0 else 0)
+ split_2 = split_1 + list_size + (1 if remainder > 1 else 0)
+
+ node_x = nodes[:split_1]
+ node_y = nodes[split_1:split_2]
+ node_z = nodes[split_2:]
+
+ pce_x = __build_pce("X", node_x, num_qubits, k)
+ pce_y = __build_pce("Y", node_y, num_qubits, k)
+ pce_z = __build_pce("Z", node_z, num_qubits, k)
+
+ cost_ops = []
+ for i in range(num_qubits - 1):
+ paulis = ["I"] * num_qubits
+ paulis[i] = "Z"
+ paulis[i + 1] = "Z"
+ cost_ops.append(("".join(paulis)[::-1], 1.0))
+
+ base_cost_op = SparsePauliOp.from_list(cost_ops)
+ reps = 3
+ qc = qaoa_ansatz(cost_operator=base_cost_op, reps=reps)
+ qc = pm.run(qc)
+
+ pce_mapped = [
+ [op.apply_layout(qc.layout) if getattr(qc, "layout", None) else op for op in pce_x],
+ [op.apply_layout(qc.layout) if getattr(qc, "layout", None) else op for op in pce_y],
+ [op.apply_layout(qc.layout) if getattr(qc, "layout", None) else op for op in pce_z],
+ ]
+
+ estimator = EstimatorV2(mode=backend)
+ exp_result = []
+
+ def loss_wrapper(x_params):
+ exp = __pce_loss(x_params, qc, pce_mapped, estimator, J_prime, num_nodes, num_qubits)
+ exp_result.append(exp)
+ return exp["loss"]
+
+ delta_t = 0.25
+ gamma_list = [(i / reps) * delta_t for i in range(1, reps + 1)]
+ beta_list = [(1 - (i / reps)) * delta_t for i in range(1, reps + 1)]
+ initial_params = beta_list + gamma_list
+
+ minimize(
+ loss_wrapper,
+ initial_params,
+ method="COBYLA",
+ options={"rhobeg": 1.0, "maxiter": len(initial_params) + 2},
+ tol=1e-4,
+ )
+
+ best_exp_map = min(exp_result, key=lambda val: val["loss"])["exp_map"]
+ best_exp_arr = np.array([best_exp_map[idx] for idx in range(num_nodes)])
+ x_raw = np.where(best_exp_arr >= 0, 1, -1)
+ x_dummy = x_raw[dummy_index]
+ x = ((1 - (x_raw[:n] * x_dummy)) // 2).astype(int)
+ H = Q @ x + x @ Q - 2 * diag_Q * x
+
+ improved = True
+ while improved:
+ improved = False
+ for u in range(n):
+ delta_z = 1 - 2 * x[u]
+ delta_E = (Q[u, u] + H[u]) * delta_z
+ if delta_E < -1e-6:
+ x[u] = 1 - x[u]
+ improved = True
+ H += (Q[u, :] + Q[:, u]) * delta_z
+ H[u] -= 2 * Q[u, u] * delta_z
+
+ powers_of_two = 2 ** np.arange(n)
+ state_int = int(np.dot(x, powers_of_two))
+
+ return {state_int: 1}
diff --git a/qsplit/adapters/ibm/__ibm_qaoa.py b/qsplit/adapters/ibm/__ibm_qaoa.py
index 8c6e758..71ced13 100644
--- a/qsplit/adapters/ibm/__ibm_qaoa.py
+++ b/qsplit/adapters/ibm/__ibm_qaoa.py
@@ -17,7 +17,8 @@
import pandas as pd
from qiskit import generate_preset_pass_manager
-from qsplit.adapters.ibm.util import get_qaoa_circuit_optimized, run_quantum_optimizer, to_dataframe
+from qsplit.adapters.ibm.util import to_dataframe
+from qsplit.adapters.ibm.util_qaoa import get_qaoa_circuit_optimized, run_quantum_optimizer
from qsplit.qubo import QUBO
diff --git a/qsplit/adapters/ibm/ibm_default.py b/qsplit/adapters/ibm/ibm_default.py
new file mode 100644
index 0000000..8f4202b
--- /dev/null
+++ b/qsplit/adapters/ibm/ibm_default.py
@@ -0,0 +1,25 @@
+# Copyright (C) 2025 The QSplit Contributors.
+# See the 'CONTRIBUTORS' file at the top-level directory of this distribution.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import pandas as pd
+from qiskit_aer import AerSimulator
+
+from qsplit.adapters.ibm.__ibm_pce import ibm_solve
+from qsplit.qubo import QUBO
+
+
+def solve(qubo: QUBO) -> pd.DataFrame:
+ return ibm_solve(qubo, AerSimulator())
diff --git a/qsplit/adapters/ibm/ibm_pce_cpu_noiseless.py b/qsplit/adapters/ibm/ibm_pce_cpu_noiseless.py
new file mode 100644
index 0000000..f3e9d84
--- /dev/null
+++ b/qsplit/adapters/ibm/ibm_pce_cpu_noiseless.py
@@ -0,0 +1,25 @@
+# Copyright (C) 2025 The QSplit Contributors.
+# See the 'CONTRIBUTORS' file at the top-level directory of this distribution.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import pandas as pd
+from qiskit_aer import AerSimulator
+
+from qsplit.adapters.ibm.__ibm_pce import ibm_pce
+from qsplit.qubo import QUBO
+
+
+def solve(qubo: QUBO) -> pd.DataFrame:
+ return ibm_pce(qubo, AerSimulator())
diff --git a/qsplit/adapters/ibm/util.py b/qsplit/adapters/ibm/util.py
index ad51476..b2d5491 100644
--- a/qsplit/adapters/ibm/util.py
+++ b/qsplit/adapters/ibm/util.py
@@ -14,228 +14,56 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-# Acknowledgement:
-# Parts of this code are adapted from the official IBM Quantum documentation
-# regarding the Quantum Approximate Optimization Algorithm (QAOA).
-# Source: https://quantum.cloud.ibm.com/docs/en/tutorials/quantum-approximate-optimization-algorithm
-# Modifications have been made to tailor the implementation to local requirements.
-
import numpy as np
import pandas as pd
-from qiskit import QuantumCircuit, generate_preset_pass_manager
-from qiskit.circuit.library import QAOAAnsatz
-from qiskit.passmanager import BasePassManager
-from qiskit.primitives import BackendEstimatorV2, BackendSamplerV2
-from qiskit.quantum_info import SparsePauliOp
-from qiskit.transpiler.exceptions import TranspilerError
-from qiskit_aer import AerSimulator
-from qiskit_algorithms.optimizers import SPSA
-from qiskit_ibm_runtime import IBMBackend
from qsplit.qubo import QUBO
-try:
- from qiskit_aer import AerSimulator
-except Exception:
- AerSimulator = None
-
-try:
- from qiskit_ibm_runtime import EstimatorV2 as RuntimeEstimatorV2
- from qiskit_ibm_runtime import IBMBackend
- from qiskit_ibm_runtime import SamplerV2 as RuntimeSamplerV2
-except Exception:
- RuntimeEstimatorV2 = None
- RuntimeSamplerV2 = None
- IBMBackend = None
-
-try:
- from qiskit.primitives import StatevectorEstimator
-except Exception:
- StatevectorEstimator = None
-
-def __get_variables_mapping(qubo: QUBO) -> tuple[dict[int, int], list[int]]:
+def get_variables_mapping(qubo: QUBO) -> tuple[dict[int, int], list[int]]:
all_vars = sorted(list(set(qubo.rows_idx) | set(qubo.cols_idx)))
var_to_qubit = {var: i for i, var in enumerate(all_vars)}
return var_to_qubit, all_vars
-def __from_qubo_matrix_to_circuit(qubo: QUBO) -> tuple[QuantumCircuit, SparsePauliOp, dict[int, int], list[int]]:
- var_to_qubit, all_vars = __get_variables_mapping(qubo)
- num_qubits = len(all_vars)
-
- pauli_list = []
-
- for i, row_var in enumerate(qubo.rows_idx):
- for j, col_var in enumerate(qubo.cols_idx):
- coeff = qubo.mat[i, j]
- if coeff == 0:
- continue
-
- if row_var == col_var:
- pauli_list.append(("Z", [var_to_qubit[row_var]], coeff))
- else:
- pauli_list.append(("ZZ", [var_to_qubit[row_var], var_to_qubit[col_var]], coeff))
-
- if qubo.offset != 0:
- pauli_list.append(("I" * num_qubits, list(range(num_qubits)), qubo.offset))
-
- cost_hamiltonian = SparsePauliOp.from_sparse_list(pauli_list, num_qubits)
- cost_hamiltonian = cost_hamiltonian.simplify()
-
- circuit = QAOAAnsatz(cost_operator=cost_hamiltonian, reps=2)
-
- return circuit, cost_hamiltonian, var_to_qubit, all_vars
-
-
-__objective_func_vals = []
-
-
-def _is_ibm_backend(backend) -> bool:
- return IBMBackend is not None and isinstance(backend, IBMBackend)
-
-
-def _is_aer_backend(backend) -> bool:
- return AerSimulator is not None and isinstance(backend, AerSimulator)
-
-
-def __optimize_circuit(
- backend,
- candidate_circuit: QuantumCircuit,
- cost_hamiltonian: SparsePauliOp,
- optimize_on_backend: bool = True,
-) -> QuantumCircuit:
- initial_gamma = np.pi
- initial_beta = np.pi / 2
- init_params = [initial_beta, initial_beta, initial_gamma, initial_gamma]
- if not optimize_on_backend:
- if StatevectorEstimator is not None:
- estimator = StatevectorEstimator()
- elif AerSimulator is not None:
- estimator = BackendEstimatorV2(
- backend=AerSimulator(method="matrix_product_state", matrix_product_state_max_bond_dimension=None)
- )
- else:
- raise RuntimeError("Local estimator backend is required when optimize_on_backend=False.")
- elif _is_ibm_backend(backend) and RuntimeEstimatorV2 is not None:
- estimator = RuntimeEstimatorV2(backend)
- else:
- estimator = BackendEstimatorV2(backend=backend)
- if optimize_on_backend and _is_ibm_backend(backend) and hasattr(estimator, "options"):
- if hasattr(estimator.options, "default_shots"):
- estimator.options.default_shots = 500
- estimator.options.dynamical_decoupling.enable = True
- estimator.options.dynamical_decoupling.sequence_type = "XY4"
- estimator.options.twirling.enable_gates = True
- estimator.options.twirling.num_randomizations = "auto"
-
- def objective_function(params: list[float]) -> float:
- return __cost_func_estimator(params, candidate_circuit, cost_hamiltonian, estimator)
-
- optimizer = SPSA()
- result = optimizer.minimize(fun=objective_function, x0=init_params)
- optimized_circuit = candidate_circuit.assign_parameters(result.x)
- return optimized_circuit
-
-
-def __cost_func_estimator(
- params: list[float], ansatz: QuantumCircuit, hamiltonian: SparsePauliOp, estimator: object
-) -> float:
- layout = getattr(ansatz, "layout", None)
- isa_hamiltonian = hamiltonian.apply_layout(layout) if layout is not None else hamiltonian
- pub = (ansatz, isa_hamiltonian, params)
- job = estimator.run([pub])
- results = job.result()[0]
- cost = results.data.evs
- __objective_func_vals.append(cost)
- return cost
-
-
-def get_qaoa_circuit_optimized(
- backend,
- pm: BasePassManager,
- qubo: QUBO,
- *,
- optimize_on_backend: bool = True,
-) -> tuple[QuantumCircuit, dict[int, int], list[int]]:
- circuit, cost_hamiltonian, var_to_qubit, all_vars = __from_qubo_matrix_to_circuit(qubo)
- if optimize_on_backend:
- try:
- candidate_circuit = pm.run(circuit)
- except TranspilerError as exc:
- if _is_aer_backend(backend) and "not in Target" in str(exc):
- try:
- candidate_circuit = generate_preset_pass_manager(optimization_level=1).run(circuit)
- except TranspilerError:
- candidate_circuit = circuit.decompose(reps=10)
- else:
- raise
- if _is_aer_backend(backend) and any(
- str(inst.operation.name).lower() == "qaoa" for inst in candidate_circuit.data
- ):
- candidate_circuit = candidate_circuit.decompose(reps=10)
- optimized_circ = __optimize_circuit(backend, candidate_circuit, cost_hamiltonian, optimize_on_backend=True)
- else:
- optimized_logical = __optimize_circuit(backend, circuit, cost_hamiltonian, optimize_on_backend=False)
- try:
- optimized_circ = pm.run(optimized_logical)
- except TranspilerError:
- optimized_circ = optimized_logical.decompose(reps=10)
- measured_circ = optimized_circ.copy()
- if measured_circ.num_clbits == 0:
- measured_circ.measure_all()
- return measured_circ, var_to_qubit, all_vars
-
-
-def run_quantum_optimizer(backend, optimized_circuit: QuantumCircuit) -> dict[int, int]:
- if _is_ibm_backend(backend) and RuntimeSamplerV2 is not None:
- sampler = RuntimeSamplerV2(mode=backend)
- else:
- sampler = BackendSamplerV2(backend=backend)
- if _is_ibm_backend(backend) and hasattr(sampler, "options"):
- sampler.options.dynamical_decoupling.enable = True
- sampler.options.dynamical_decoupling.sequence_type = "XY4"
- sampler.options.twirling.enable_gates = True
- sampler.options.twirling.num_randomizations = "auto"
- pub = (optimized_circuit,)
- job = sampler.run([pub], shots=500)
- data_bin = job.result()[0].data
- keys_method = getattr(data_bin, "keys", None)
- available_keys = list(keys_method()) if callable(keys_method) else []
- if hasattr(data_bin, "meas") and hasattr(data_bin.meas, "get_int_counts"):
- return data_bin.meas.get_int_counts()
- if hasattr(data_bin, "c") and hasattr(data_bin.c, "get_int_counts"):
- return data_bin.c.get_int_counts()
- if available_keys:
- for key in available_keys:
- reg = getattr(data_bin, key, None)
- if reg is not None and hasattr(reg, "get_int_counts"):
- return reg.get_int_counts()
- raise RuntimeError("No readable classical register found in SamplerV2 result")
-
-
def to_dataframe(
counts_int: dict[int, int], qubo: QUBO, var_to_qubit: dict[int, int], all_vars: list[int]
) -> pd.DataFrame:
data = []
num_qubits = len(all_vars)
- for state_int, count in counts_int.items():
+ valid_row_mask = [i for i, r in enumerate(qubo.rows_idx) if r != -1]
+ valid_col_mask = [i for i, c in enumerate(qubo.cols_idx) if c != -1]
+
+ valid_rows_idx = [qubo.rows_idx[i] for i in valid_row_mask]
+ valid_cols_idx = [qubo.cols_idx[i] for i in valid_col_mask]
+
+ mat_valid = qubo.mat[np.ix_(valid_row_mask, valid_col_mask)]
+
+ for state_int, _ in counts_int.items():
bin_str = np.binary_repr(state_int, width=num_qubits)
full_solution = np.array([int(bit) for bit in bin_str])[::-1]
+
sol_dict = {var_name: full_solution[q_idx] for var_name, q_idx in var_to_qubit.items()}
- vec_row = np.array([sol_dict[r] for r in qubo.rows_idx])
- vec_col = np.array([sol_dict[c] for c in qubo.cols_idx])
- energy = vec_row @ qubo.mat @ vec_col.T
+
+ vec_row = np.array([sol_dict[r] for r in valid_rows_idx])
+ vec_col = np.array([sol_dict[c] for c in valid_cols_idx])
+ energy = vec_row @ mat_valid @ vec_col.T
+
+ if -1 in sol_dict:
+ del sol_dict[-1]
+
row = sol_dict.copy()
row["energy"] = energy
data.append(row)
res = pd.DataFrame(data)
res = res.sort_values(by="energy", ascending=True)
- cols = [c for c in res.columns if c not in ["energy"]]
+
+ cols = [c for c in res.columns if c != "energy"]
cols.sort()
res = res[cols + ["energy"]]
+
best_energy = res["energy"].min()
return res[res["energy"] == best_energy]
diff --git a/qsplit/adapters/ibm/util_qaoa.py b/qsplit/adapters/ibm/util_qaoa.py
new file mode 100644
index 0000000..358b373
--- /dev/null
+++ b/qsplit/adapters/ibm/util_qaoa.py
@@ -0,0 +1,208 @@
+# Copyright (C) 2025 The QSplit Contributors.
+# See the 'CONTRIBUTORS' file at the top-level directory of this distribution.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+# Acknowledgement:
+# Parts of this code are adapted from the official IBM Quantum documentation
+# regarding the Quantum Approximate Optimization Algorithm (QAOA).
+# Source: https://quantum.cloud.ibm.com/docs/en/tutorials/quantum-approximate-optimization-algorithm
+# Modifications have been made to tailor the implementation to local requirements.
+
+import numpy as np
+from qiskit import QuantumCircuit, generate_preset_pass_manager
+from qiskit.circuit.library import QAOAAnsatz
+from qiskit.passmanager import BasePassManager
+from qiskit.primitives import BackendEstimatorV2, BackendSamplerV2
+from qiskit.quantum_info import SparsePauliOp
+from qiskit.transpiler.exceptions import TranspilerError
+from qiskit_aer import AerSimulator
+from qiskit_algorithms.optimizers import SPSA
+from qiskit_ibm_runtime import IBMBackend
+
+from qsplit.adapters.ibm.util import get_variables_mapping
+from qsplit.qubo import QUBO
+
+try:
+ from qiskit_aer import AerSimulator
+except Exception:
+ AerSimulator = None
+
+try:
+ from qiskit_ibm_runtime import EstimatorV2 as RuntimeEstimatorV2
+ from qiskit_ibm_runtime import IBMBackend
+ from qiskit_ibm_runtime import SamplerV2 as RuntimeSamplerV2
+except Exception:
+ RuntimeEstimatorV2 = None
+ RuntimeSamplerV2 = None
+ IBMBackend = None
+
+try:
+ from qiskit.primitives import StatevectorEstimator
+except Exception:
+ StatevectorEstimator = None
+
+
+def __from_qubo_matrix_to_circuit(qubo: QUBO) -> tuple[QuantumCircuit, SparsePauliOp, dict[int, int], list[int]]:
+ var_to_qubit, all_vars = get_variables_mapping(qubo)
+ num_qubits = len(all_vars)
+
+ pauli_list = []
+
+ for i, row_var in enumerate(qubo.rows_idx):
+ for j, col_var in enumerate(qubo.cols_idx):
+ coeff = qubo.mat[i, j]
+ if coeff == 0:
+ continue
+
+ if row_var == col_var:
+ pauli_list.append(("Z", [var_to_qubit[row_var]], coeff))
+ else:
+ pauli_list.append(("ZZ", [var_to_qubit[row_var], var_to_qubit[col_var]], coeff))
+
+ if qubo.offset != 0:
+ pauli_list.append(("I" * num_qubits, list(range(num_qubits)), qubo.offset))
+
+ cost_hamiltonian = SparsePauliOp.from_sparse_list(pauli_list, num_qubits)
+ cost_hamiltonian = cost_hamiltonian.simplify()
+
+ circuit = QAOAAnsatz(cost_operator=cost_hamiltonian, reps=2)
+
+ return circuit, cost_hamiltonian, var_to_qubit, all_vars
+
+
+__objective_func_vals = []
+
+
+def _is_ibm_backend(backend) -> bool:
+ return IBMBackend is not None and isinstance(backend, IBMBackend)
+
+
+def _is_aer_backend(backend) -> bool:
+ return AerSimulator is not None and isinstance(backend, AerSimulator)
+
+
+def __optimize_circuit(
+ backend,
+ candidate_circuit: QuantumCircuit,
+ cost_hamiltonian: SparsePauliOp,
+ optimize_on_backend: bool = True,
+) -> QuantumCircuit:
+ initial_gamma = np.pi
+ initial_beta = np.pi / 2
+ init_params = [initial_beta, initial_beta, initial_gamma, initial_gamma]
+ if not optimize_on_backend:
+ if StatevectorEstimator is not None:
+ estimator = StatevectorEstimator()
+ elif AerSimulator is not None:
+ estimator = BackendEstimatorV2(
+ backend=AerSimulator(method="matrix_product_state", matrix_product_state_max_bond_dimension=None)
+ )
+ else:
+ raise RuntimeError("Local estimator backend is required when optimize_on_backend=False.")
+ elif _is_ibm_backend(backend) and RuntimeEstimatorV2 is not None:
+ estimator = RuntimeEstimatorV2(backend)
+ else:
+ estimator = BackendEstimatorV2(backend=backend)
+ if optimize_on_backend and _is_ibm_backend(backend) and hasattr(estimator, "options"):
+ if hasattr(estimator.options, "default_shots"):
+ estimator.options.default_shots = 500
+ estimator.options.dynamical_decoupling.enable = True
+ estimator.options.dynamical_decoupling.sequence_type = "XY4"
+ estimator.options.twirling.enable_gates = True
+ estimator.options.twirling.num_randomizations = "auto"
+
+ def objective_function(params: list[float]) -> float:
+ return __cost_func_estimator(params, candidate_circuit, cost_hamiltonian, estimator)
+
+ optimizer = SPSA()
+ result = optimizer.minimize(fun=objective_function, x0=init_params)
+ optimized_circuit = candidate_circuit.assign_parameters(result.x)
+ return optimized_circuit
+
+
+def __cost_func_estimator(
+ params: list[float], ansatz: QuantumCircuit, hamiltonian: SparsePauliOp, estimator: object
+) -> float:
+ layout = getattr(ansatz, "layout", None)
+ isa_hamiltonian = hamiltonian.apply_layout(layout) if layout is not None else hamiltonian
+ pub = (ansatz, isa_hamiltonian, params)
+ job = estimator.run([pub])
+ results = job.result()[0]
+ cost = results.data.evs
+ __objective_func_vals.append(cost)
+ return cost
+
+
+def get_qaoa_circuit_optimized(
+ backend,
+ pm: BasePassManager,
+ qubo: QUBO,
+ *,
+ optimize_on_backend: bool = True,
+) -> tuple[QuantumCircuit, dict[int, int], list[int]]:
+ circuit, cost_hamiltonian, var_to_qubit, all_vars = __from_qubo_matrix_to_circuit(qubo)
+ if optimize_on_backend:
+ try:
+ candidate_circuit = pm.run(circuit)
+ except TranspilerError as exc:
+ if _is_aer_backend(backend) and "not in Target" in str(exc):
+ try:
+ candidate_circuit = generate_preset_pass_manager(optimization_level=1).run(circuit)
+ except TranspilerError:
+ candidate_circuit = circuit.decompose(reps=10)
+ else:
+ raise
+ if _is_aer_backend(backend) and any(
+ str(inst.operation.name).lower() == "qaoa" for inst in candidate_circuit.data
+ ):
+ candidate_circuit = candidate_circuit.decompose(reps=10)
+ optimized_circ = __optimize_circuit(backend, candidate_circuit, cost_hamiltonian, optimize_on_backend=True)
+ else:
+ optimized_logical = __optimize_circuit(backend, circuit, cost_hamiltonian, optimize_on_backend=False)
+ try:
+ optimized_circ = pm.run(optimized_logical)
+ except TranspilerError:
+ optimized_circ = optimized_logical.decompose(reps=10)
+ measured_circ = optimized_circ.copy()
+ if measured_circ.num_clbits == 0:
+ measured_circ.measure_all()
+ return measured_circ, var_to_qubit, all_vars
+
+
+def run_quantum_optimizer(backend, optimized_circuit: QuantumCircuit) -> dict[int, int]:
+ if _is_ibm_backend(backend) and RuntimeSamplerV2 is not None:
+ sampler = RuntimeSamplerV2(mode=backend)
+ else:
+ sampler = BackendSamplerV2(backend=backend)
+ if _is_ibm_backend(backend) and hasattr(sampler, "options"):
+ sampler.options.dynamical_decoupling.enable = True
+ sampler.options.dynamical_decoupling.sequence_type = "XY4"
+ sampler.options.twirling.enable_gates = True
+ sampler.options.twirling.num_randomizations = "auto"
+ pub = (optimized_circuit,)
+ job = sampler.run([pub], shots=500)
+ data_bin = job.result()[0].data
+ keys_method = getattr(data_bin, "keys", None)
+ available_keys = list(keys_method()) if callable(keys_method) else []
+ if hasattr(data_bin, "meas") and hasattr(data_bin.meas, "get_int_counts"):
+ return data_bin.meas.get_int_counts()
+ if hasattr(data_bin, "c") and hasattr(data_bin.c, "get_int_counts"):
+ return data_bin.c.get_int_counts()
+ if available_keys:
+ for key in available_keys:
+ reg = getattr(data_bin, key, None)
+ if reg is not None and hasattr(reg, "get_int_counts"):
+ return reg.get_int_counts()
+ raise RuntimeError("No readable classical register found in SamplerV2 result")
diff --git a/tests/test_ibm_adapter.py b/tests/test_ibm_adapter.py
index b56354d..e0f327f 100644
--- a/tests/test_ibm_adapter.py
+++ b/tests/test_ibm_adapter.py
@@ -22,9 +22,8 @@
from qiskit.quantum_info import SparsePauliOp
from qsplit.adapters.ibm.ibm_qaoa_cpu_noiseless import solve as cpu_solve
-from qsplit.adapters.ibm.util import __from_qubo_matrix_to_circuit as from_qubo_matrix_to_circuit
-from qsplit.adapters.ibm.util import __get_variables_mapping as get_variables_mapping
-from qsplit.adapters.ibm.util import to_dataframe
+from qsplit.adapters.ibm.util import get_variables_mapping, to_dataframe
+from qsplit.adapters.ibm.util_qaoa import __from_qubo_matrix_to_circuit as from_qubo_matrix_to_circuit
from qsplit.qubo import QUBO
@@ -156,7 +155,6 @@ def test_to_dataframe_with_padding_variable(self):
self.assertEqual(df.iloc[0]["energy"], 0.0)
self.assertEqual(df.iloc[0][1], 0)
- self.assertIn(-1, df.columns)
##################################################
# cpu_noiseless #
diff --git a/uv.lock b/uv.lock
index 07bf104..b6bc5eb 100644
--- a/uv.lock
+++ b/uv.lock
@@ -209,8 +209,7 @@ name = "astunparse"
version = "1.6.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "six", version = "1.16.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.13' and extra == 'extra-6-qsplit-iqm') or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-gpu' and extra == 'extra-6-qsplit-quantinuum') or (extra == 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-quantinuum') or (extra == 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-streamflow')" },
- { name = "six", version = "1.17.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13' or extra != 'extra-6-qsplit-iqm' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-quantinuum') or (extra == 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-streamflow')" },
+ { name = "six" },
{ name = "wheel" },
]
sdist = { url = "https://files.pythonhosted.org/packages/f3/af/4182184d3c338792894f34a62672919db7ca008c89abee9b564dd34d8029/astunparse-1.6.3.tar.gz", hash = "sha256:5ad93a8456f0d084c3456d059fd9a92cce667963232cbf763eac3bc5b7940872", size = 18290, upload-time = "2019-12-22T18:12:13.129Z" }
@@ -777,7 +776,7 @@ name = "cwl-upgrader"
version = "1.2.14"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "ruamel-yaml", version = "0.18.17", source = { registry = "https://pypi.org/simple" } },
+ { name = "ruamel-yaml" },
{ name = "schema-salad" },
]
sdist = { url = "https://files.pythonhosted.org/packages/9c/21/bde273967127242d991c6ef63c427f9d75ced2a883859544381dae752ec3/cwl_upgrader-1.2.14.tar.gz", hash = "sha256:a20de876a666bb1510d37310d4225fc6df6572e314d1cb6c2202b742a0d76db6", size = 22095, upload-time = "2025-12-21T11:51:21.776Z" }
@@ -794,7 +793,7 @@ dependencies = [
{ name = "packaging", version = "26.0", source = { registry = "https://pypi.org/simple" } },
{ name = "rdflib" },
{ name = "requests", version = "2.32.5", source = { registry = "https://pypi.org/simple" } },
- { name = "ruamel-yaml", version = "0.18.17", source = { registry = "https://pypi.org/simple" } },
+ { name = "ruamel-yaml" },
{ name = "schema-salad" },
]
sdist = { url = "https://files.pythonhosted.org/packages/7f/00/80a18397dd81fc39ad5b61af227becebc9d537bcb679d14731023b0bee4a/cwl_utils-0.40.tar.gz", hash = "sha256:fb836fe71617e10cfefb74cfcb2ab7b4a6e36b36cebf2f04b3fb43e15bc74751", size = 365488, upload-time = "2025-09-09T20:53:57.952Z" }
@@ -1638,25 +1637,24 @@ wheels = [
[[package]]
name = "iqm-exa-common"
-version = "27.4.5"
+version = "27.5.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "iqm-data-definitions", marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
{ name = "jinja2", marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
{ name = "numpy", marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
{ name = "pydantic", marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
- { name = "python-dotenv", version = "0.21.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
+ { name = "python-dotenv", marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
{ name = "requests", version = "2.32.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
- { name = "ruamel-yaml", version = "0.17.32", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
- { name = "ruamel-yaml-clib", version = "0.2.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
- { name = "six", version = "1.16.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
+ { name = "ruamel-yaml", marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
+ { name = "six", marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
{ name = "types-requests", marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
{ name = "types-six", marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
{ name = "xarray", marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/66/56/98827160372a1ab149ab626afe334da59aed1309b64d1dde27e9de8b2e30/iqm_exa_common-27.4.5.tar.gz", hash = "sha256:42caa485bcdb8ea833adf2f03c0f8e36dc4cfa606acaa44ccba89637a496b253", size = 239597, upload-time = "2026-02-18T17:20:50.988Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/00/e27a6eb472b74164c2e27cd64055ae1ebf02be45e9e718729ce7f4a20a9e/iqm_exa_common-27.5.3.tar.gz", hash = "sha256:8c18490d226169afc3923a6ad472705898503c75271811ca42d415f053b56ca7", size = 272000, upload-time = "2026-05-06T13:13:05.314Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/38/8e/338f62cf1cf2cb2d1440dc6dbf22fa86fec9fc88b7c642a9374da52a4a8f/iqm_exa_common-27.4.5-py3-none-any.whl", hash = "sha256:5dda62e66178d0ff31836e7eba9507230e4da52598bb61e6514594d998f017e5", size = 89879, upload-time = "2026-02-18T17:20:48.531Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/56/63499f5a58ff58c9e775edf323f5268199882d58b4ed1f3f3954c518e452/iqm_exa_common-27.5.3-py3-none-any.whl", hash = "sha256:1977173a8f6fae4c6c3f53c0f5f3a571c628ee94930716cb512dcf58118dfe44", size = 95169, upload-time = "2026-05-06T13:13:03.564Z" },
]
[[package]]
@@ -1819,7 +1817,7 @@ dependencies = [
{ name = "certifi" },
{ name = "python-dateutil" },
{ name = "pyyaml" },
- { name = "six", version = "1.17.0", source = { registry = "https://pypi.org/simple" } },
+ { name = "six" },
{ name = "urllib3" },
]
sdist = { url = "https://files.pythonhosted.org/packages/34/1f/b4312300a1e38c5896b4f5476a546f4a7c86fdd2d53b404699c3dd578bb0/kubernetes_asyncio-34.3.3.tar.gz", hash = "sha256:9f6f30f9745371b26b0bc922be6a3f81c0d6b3400e9f63d0aa1b92aa49cfcc48", size = 1274583, upload-time = "2026-01-12T23:15:27.78Z" }
@@ -3010,7 +3008,7 @@ version = "2.13.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pydantic" },
- { name = "python-dotenv", version = "1.2.1", source = { registry = "https://pypi.org/simple" } },
+ { name = "python-dotenv" },
{ name = "typing-inspection" },
]
sdist = { url = "https://files.pythonhosted.org/packages/52/6d/fffca34caecc4a3f97bda81b2098da5e8ab7efc9a66e819074a11955d87e/pydantic_settings-2.13.1.tar.gz", hash = "sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025", size = 223826, upload-time = "2026-02-19T13:45:08.055Z" }
@@ -3103,26 +3101,13 @@ name = "python-dateutil"
version = "2.9.0.post0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "six", version = "1.16.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.13' and extra == 'extra-6-qsplit-iqm') or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-gpu' and extra == 'extra-6-qsplit-quantinuum') or (extra == 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-quantinuum') or (extra == 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-streamflow')" },
- { name = "six", version = "1.17.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13' or extra != 'extra-6-qsplit-iqm' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-quantinuum') or (extra == 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-streamflow')" },
+ { name = "six" },
]
sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
]
-[[package]]
-name = "python-dotenv"
-version = "0.21.1"
-source = { registry = "https://pypi.org/simple" }
-resolution-markers = [
- "python_full_version < '3.13'",
-]
-sdist = { url = "https://files.pythonhosted.org/packages/f5/d7/d548e0d5a68b328a8d69af833a861be415a17cb15ce3d8f0cd850073d2e1/python-dotenv-0.21.1.tar.gz", hash = "sha256:1c93de8f636cde3ce377292818d0e440b6e45a82f215c3744979151fa8151c49", size = 35930, upload-time = "2023-01-21T10:22:47.277Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/64/62/f19d1e9023aacb47241de3ab5a5d5fedf32c78a71a9e365bb2153378c141/python_dotenv-0.21.1-py3-none-any.whl", hash = "sha256:41e12e0318bebc859fcc4d97d4db8d20ad21721a6aa5047dd59f090391cb549a", size = 19284, upload-time = "2023-01-21T10:22:45.958Z" },
-]
-
[[package]]
name = "python-dotenv"
version = "1.2.1"
@@ -3824,49 +3809,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d0/02/fa464cdfbe6b26e0600b62c528b72d8608f5cc49f96b8d6e38c95d60c676/rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3", size = 226532, upload-time = "2025-11-30T20:24:14.634Z" },
]
-[[package]]
-name = "ruamel-yaml"
-version = "0.17.32"
-source = { registry = "https://pypi.org/simple" }
-resolution-markers = [
- "python_full_version < '3.13'",
-]
-sdist = { url = "https://files.pythonhosted.org/packages/63/dd/b4719a290e49015536bd0ab06ab13e3b468d8697bec6c2f668ac48b05661/ruamel.yaml-0.17.32.tar.gz", hash = "sha256:ec939063761914e14542972a5cba6d33c23b0859ab6342f61cf070cfc600efc2", size = 134455, upload-time = "2023-06-17T05:58:01.15Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/d9/0e/2a05efa11ea33513fbdf4a2e2576fe94fd8fa5ad226dbb9c660886390974/ruamel.yaml-0.17.32-py3-none-any.whl", hash = "sha256:23cd2ed620231677564646b0c6a89d138b6822a0d78656df7abda5879ec4f447", size = 112158, upload-time = "2023-06-17T05:58:04.22Z" },
-]
-
[[package]]
name = "ruamel-yaml"
version = "0.18.17"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "ruamel-yaml-clib", version = "0.2.15", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.15' and platform_python_implementation == 'CPython') or (python_full_version >= '3.15' and extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (python_full_version >= '3.15' and extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu') or (python_full_version >= '3.15' and extra == 'extra-6-qsplit-ibm-gpu' and extra == 'extra-6-qsplit-quantinuum') or (platform_python_implementation != 'CPython' and extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (platform_python_implementation != 'CPython' and extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu') or (platform_python_implementation != 'CPython' and extra == 'extra-6-qsplit-ibm-gpu' and extra == 'extra-6-qsplit-quantinuum')" },
+ { name = "ruamel-yaml-clib", marker = "(python_full_version >= '3.13' and python_full_version < '3.15' and extra == 'extra-6-qsplit-ibm-gpu' and extra == 'extra-6-qsplit-quantinuum') or (python_full_version >= '3.13' and python_full_version < '3.15' and extra == 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-quantinuum') or (python_full_version >= '3.13' and python_full_version < '3.15' and extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-streamflow') or (python_full_version >= '3.13' and python_full_version < '3.15' and extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-streamflow') or (python_full_version >= '3.13' and python_full_version < '3.15' and extra != 'extra-6-qsplit-ibm-gpu' and extra == 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-streamflow') or (python_full_version < '3.13' and platform_python_implementation == 'CPython' and extra == 'extra-6-qsplit-iqm') or (python_full_version < '3.13' and platform_python_implementation == 'CPython' and extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-streamflow') or (python_full_version < '3.13' and platform_python_implementation == 'CPython' and extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-streamflow') or (python_full_version < '3.13' and platform_python_implementation == 'CPython' and extra != 'extra-6-qsplit-ibm-gpu' and extra == 'extra-6-qsplit-streamflow') or (python_full_version < '3.13' and platform_python_implementation == 'CPython' and extra == 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-quantinuum' and extra == 'extra-6-qsplit-streamflow') or (python_full_version < '3.15' and platform_python_implementation == 'CPython' and extra == 'extra-6-qsplit-dev' and extra != 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-streamflow') or (python_full_version < '3.15' and platform_python_implementation == 'CPython' and extra == 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-streamflow') or (python_full_version < '3.15' and platform_python_implementation == 'CPython' and extra == 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-quantinuum' and extra == 'extra-6-qsplit-streamflow') or (python_full_version < '3.15' and platform_python_implementation == 'CPython' and extra != 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-streamflow') or (python_full_version >= '3.15' and extra == 'extra-6-qsplit-ibm-gpu' and extra == 'extra-6-qsplit-quantinuum') or (python_full_version >= '3.15' and extra == 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-quantinuum') or (python_full_version >= '3.15' and extra == 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-streamflow') or (python_full_version < '3.13' and extra == 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-quantinuum') or (platform_python_implementation != 'CPython' and extra == 'extra-6-qsplit-ibm-gpu' and extra == 'extra-6-qsplit-quantinuum') or (platform_python_implementation != 'CPython' and extra == 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-quantinuum') or (platform_python_implementation != 'CPython' and extra == 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-streamflow') or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/3a/2b/7a1f1ebcd6b3f14febdc003e658778d81e76b40df2267904ee6b13f0c5c6/ruamel_yaml-0.18.17.tar.gz", hash = "sha256:9091cd6e2d93a3a4b157ddb8fabf348c3de7f1fb1381346d985b6b247dcd8d3c", size = 149602, upload-time = "2025-12-17T20:02:55.757Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/af/fe/b6045c782f1fd1ae317d2a6ca1884857ce5c20f59befe6ab25a8603c43a7/ruamel_yaml-0.18.17-py3-none-any.whl", hash = "sha256:9c8ba9eb3e793efdf924b60d521820869d5bf0cb9c6f1b82d82de8295e290b9d", size = 121594, upload-time = "2025-12-17T20:02:07.657Z" },
]
-[[package]]
-name = "ruamel-yaml-clib"
-version = "0.2.8"
-source = { registry = "https://pypi.org/simple" }
-resolution-markers = [
- "python_full_version < '3.13'",
-]
-sdist = { url = "https://files.pythonhosted.org/packages/46/ab/bab9eb1566cd16f060b54055dd39cf6a34bfa0240c53a7218c43e974295b/ruamel.yaml.clib-0.2.8.tar.gz", hash = "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512", size = 213824, upload-time = "2023-10-03T18:12:42.315Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/7a/a2/eb5e9d088cb9d15c24d956944c09dca0a89108ad6e2e913c099ef36e3f0d/ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1", size = 144636, upload-time = "2023-10-03T18:13:09.564Z" },
- { url = "https://files.pythonhosted.org/packages/66/98/8de4f22bbfd9135deb3422e96d450c4bc0a57d38c25976119307d2efe0aa/ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2", size = 135684, upload-time = "2023-10-03T18:13:12.11Z" },
- { url = "https://files.pythonhosted.org/packages/30/d3/5fe978cd01a61c12efd24d65fa68c6f28f28c8073a06cf11db3a854390ca/ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92", size = 734571, upload-time = "2023-10-03T18:13:14.523Z" },
- { url = "https://files.pythonhosted.org/packages/55/b3/e2531a050758b717c969cbf76c103b75d8a01e11af931b94ba656117fbe9/ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_24_aarch64.whl", hash = "sha256:1dc67314e7e1086c9fdf2680b7b6c2be1c0d8e3a8279f2e993ca2a7545fecf62", size = 643946, upload-time = "2023-11-09T07:40:20.598Z" },
- { url = "https://files.pythonhosted.org/packages/0d/aa/06db7ca0995b513538402e11280282c615b5ae5f09eb820460d35fb69715/ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3213ece08ea033eb159ac52ae052a4899b56ecc124bb80020d9bbceeb50258e9", size = 692169, upload-time = "2023-10-22T15:35:38.378Z" },
- { url = "https://files.pythonhosted.org/packages/27/38/4cf4d482b84ecdf51efae6635cc5483a83cf5ca9d9c13e205a750e251696/ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aab7fd643f71d7946f2ee58cc88c9b7bfc97debd71dcc93e03e2d174628e7e2d", size = 740325, upload-time = "2023-10-22T15:35:40.03Z" },
- { url = "https://files.pythonhosted.org/packages/6f/67/c62c6eea53a4feb042727a3d6c18f50dc99683c2b199c06bd2a9e3db8e22/ruamel.yaml.clib-0.2.8-cp312-cp312-win32.whl", hash = "sha256:5c365d91c88390c8d0a8545df0b5857172824b1c604e867161e6b3d59a827eaa", size = 98639, upload-time = "2023-10-22T15:01:25.115Z" },
- { url = "https://files.pythonhosted.org/packages/10/d2/52a3d810d0b5b3720725c0504a27b3fced7b6f310fe928f7019d79387bc1/ruamel.yaml.clib-0.2.8-cp312-cp312-win_amd64.whl", hash = "sha256:1758ce7d8e1a29d23de54a16ae867abd370f01b5a69e1a3ba75223eaa3ca1a1b", size = 115305, upload-time = "2023-10-22T15:01:27.265Z" },
-]
-
[[package]]
name = "ruamel-yaml-clib"
version = "0.2.15"
@@ -3962,7 +3916,7 @@ dependencies = [
{ name = "mypy-extensions" },
{ name = "rdflib" },
{ name = "requests", version = "2.32.5", source = { registry = "https://pypi.org/simple" } },
- { name = "ruamel-yaml", version = "0.18.17", source = { registry = "https://pypi.org/simple" } },
+ { name = "ruamel-yaml" },
]
sdist = { url = "https://files.pythonhosted.org/packages/82/06/5a230cd2caeb0a642abafe1631db860d92731d5fdab724c54465c6766aab/schema_salad-8.9.20251102115403.tar.gz", hash = "sha256:66b535d8f18ed16436aa400f785b0acca9d757064aaefd311dbe2043c1737286", size = 602347, upload-time = "2025-11-02T12:11:17.998Z" }
wheels = [
@@ -4081,47 +4035,10 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e1/c6/76dc613121b793286a3f91621d7b75a2b493e0390ddca50f11993eadf192/setuptools-82.0.0-py3-none-any.whl", hash = "sha256:70b18734b607bd1da571d097d236cfcfacaf01de45717d59e6e04b96877532e0", size = 1003468, upload-time = "2026-02-08T15:08:38.723Z" },
]
-[[package]]
-name = "six"
-version = "1.16.0"
-source = { registry = "https://pypi.org/simple" }
-resolution-markers = [
- "python_full_version < '3.13'",
-]
-sdist = { url = "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", size = 34041, upload-time = "2021-05-05T14:18:18.379Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", size = 11053, upload-time = "2021-05-05T14:18:17.237Z" },
-]
-
[[package]]
name = "six"
version = "1.17.0"
source = { registry = "https://pypi.org/simple" }
-resolution-markers = [
- "extra != 'extra-6-qsplit-dev' and extra != 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra != 'extra-6-qsplit-quantinuum' and extra == 'extra-6-qsplit-streamflow'",
- "python_full_version >= '3.13' and extra != 'extra-6-qsplit-dev' and extra != 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu' and extra == 'extra-6-qsplit-iqm' and extra != 'extra-6-qsplit-quantinuum' and extra != 'extra-6-qsplit-streamflow'",
- "extra != 'extra-6-qsplit-dev' and extra != 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra != 'extra-6-qsplit-quantinuum' and extra != 'extra-6-qsplit-streamflow'",
- "extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-quantinuum' and extra == 'extra-6-qsplit-streamflow'",
- "extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-quantinuum' and extra != 'extra-6-qsplit-streamflow'",
- "extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra != 'extra-6-qsplit-quantinuum' and extra == 'extra-6-qsplit-streamflow'",
- "python_full_version >= '3.13' and extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra == 'extra-6-qsplit-iqm' and extra != 'extra-6-qsplit-quantinuum' and extra != 'extra-6-qsplit-streamflow'",
- "extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra != 'extra-6-qsplit-quantinuum' and extra != 'extra-6-qsplit-streamflow'",
- "extra != 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-quantinuum' and extra == 'extra-6-qsplit-streamflow'",
- "extra != 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-quantinuum' and extra != 'extra-6-qsplit-streamflow'",
- "extra != 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra != 'extra-6-qsplit-quantinuum' and extra == 'extra-6-qsplit-streamflow'",
- "python_full_version >= '3.13' and extra != 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra == 'extra-6-qsplit-iqm' and extra != 'extra-6-qsplit-quantinuum' and extra != 'extra-6-qsplit-streamflow'",
- "extra != 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra != 'extra-6-qsplit-quantinuum' and extra != 'extra-6-qsplit-streamflow'",
- "extra == 'extra-6-qsplit-dev' and extra != 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-quantinuum' and extra == 'extra-6-qsplit-streamflow'",
- "extra == 'extra-6-qsplit-dev' and extra != 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-quantinuum' and extra != 'extra-6-qsplit-streamflow'",
- "extra == 'extra-6-qsplit-dev' and extra != 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra != 'extra-6-qsplit-quantinuum' and extra == 'extra-6-qsplit-streamflow'",
- "python_full_version >= '3.13' and extra == 'extra-6-qsplit-dev' and extra != 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra == 'extra-6-qsplit-iqm' and extra != 'extra-6-qsplit-quantinuum' and extra != 'extra-6-qsplit-streamflow'",
- "extra == 'extra-6-qsplit-dev' and extra != 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra != 'extra-6-qsplit-quantinuum' and extra != 'extra-6-qsplit-streamflow'",
- "extra != 'extra-6-qsplit-dev' and extra != 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-quantinuum' and extra == 'extra-6-qsplit-streamflow'",
- "extra != 'extra-6-qsplit-dev' and extra != 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra == 'extra-6-qsplit-quantinuum' and extra != 'extra-6-qsplit-streamflow'",
- "extra != 'extra-6-qsplit-dev' and extra != 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra != 'extra-6-qsplit-quantinuum' and extra == 'extra-6-qsplit-streamflow'",
- "python_full_version >= '3.13' and extra != 'extra-6-qsplit-dev' and extra != 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra == 'extra-6-qsplit-iqm' and extra != 'extra-6-qsplit-quantinuum' and extra != 'extra-6-qsplit-streamflow'",
- "extra != 'extra-6-qsplit-dev' and extra != 'extra-6-qsplit-ibm-cpu' and extra != 'extra-6-qsplit-ibm-gpu' and extra != 'extra-6-qsplit-iqm' and extra != 'extra-6-qsplit-quantinuum' and extra != 'extra-6-qsplit-streamflow'",
-]
sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
@@ -4502,16 +4419,16 @@ wheels = [
[[package]]
name = "xarray"
-version = "2026.2.0"
+version = "2024.10.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "numpy", marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
{ name = "packaging", version = "24.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
{ name = "pandas", marker = "python_full_version < '3.13' or (extra == 'extra-6-qsplit-dev' and extra == 'extra-6-qsplit-ibm-gpu') or (extra == 'extra-6-qsplit-ibm-cpu' and extra == 'extra-6-qsplit-ibm-gpu')" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/0f/03/e3353b72e518574b32993989d8f696277bf878e9d508c7dd22e86c0dab5b/xarray-2026.2.0.tar.gz", hash = "sha256:978b6acb018770554f8fd964af4eb02f9bcc165d4085dbb7326190d92aa74bcf", size = 3111388, upload-time = "2026-02-13T22:20:50.18Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/b7/f2/a3e3ec1ffd29b0b5be800d2606c229f04f303ee9e61a1377dc5c1996cf8a/xarray-2024.10.0.tar.gz", hash = "sha256:e369e2bac430e418c2448e5b96f07da4635f98c1319aa23cfeb3fbcb9a01d2e0", size = 3788358, upload-time = "2024-10-24T21:45:48.532Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/99/92/545eb2ca17fc0e05456728d7e4378bfee48d66433ae3b7e71948e46826fb/xarray-2026.2.0-py3-none-any.whl", hash = "sha256:e927d7d716ea71dea78a13417970850a640447d8dd2ceeb65c5687f6373837c9", size = 1405358, upload-time = "2026-02-13T22:20:47.847Z" },
+ { url = "https://files.pythonhosted.org/packages/a9/b7/9830def68e5575a24ca6d6f46b285d35ed27860beaa4f72848cd82870253/xarray-2024.10.0-py3-none-any.whl", hash = "sha256:ae1d38cb44a0324dfb61e492394158ae22389bf7de9f3c174309c17376df63a0", size = 1212984, upload-time = "2024-10-24T21:45:46.566Z" },
]
[[package]]