Source code for qiskit_optimization.applications.sk_model

# This code is part of a Qiskit project.
#
# (C) Copyright IBM 2021, 2025.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""An application class for the Sherrington Kirkpatrick (SK) model."""
from __future__ import annotations


import networkx as nx
import numpy as np
from docplex.mp.model import Model

from .graph_optimization_application import OptimizationApplication
from ..algorithms import OptimizationResult
from ..problems.quadratic_program import QuadraticProgram
from ..translators import from_docplex_mp


[docs] class SKModel(OptimizationApplication): r"""Optimization application of the "Sherrington Kirkpatrick (SK) model" [1]. The SK Hamiltonian over n spins is given as: :math:`H(x)=-1/\sqrt{n} \sum_{i<j} w_{i,j}x_ix_j`, where :math:`x_i\in\{\pm 1\}` is the configuration of spins and :math:`w_{i,j}\in\{\pm 1\}` is a disorder chosen independently and uniformly at random. Notice that there are other variants of disorders e.g., with :math:`w_{i,j}` chosen from the normal distribution with mean 0 and variance 1. References: [1]: Dmitry Panchenko. "The Sherrington-Kirkpatrick model: an overview", https://arxiv.org/abs/1211.1094 """ def __init__(self, num_sites: int, rng_or_seed: np.random.Generator | int | None = None): """ Args: num_sites: number of sites rng_or_seed: NumPy pseudo-random number generator or seed for np.random.default_rng(<seed>) or None. None results in usage of np.random.default_rng(). """ if isinstance(rng_or_seed, np.random.Generator): self._rng = rng_or_seed else: self._rng = np.random.default_rng(rng_or_seed) self._num_sites = num_sites self._graph = nx.complete_graph(self._num_sites) self.disorder()
[docs] def disorder(self) -> None: """Generate a new disorder of the SK model.""" for _, _, edge_data in self._graph.edges(data=True): edge_data["weight"] = self._rng.choice([-1, 1])
[docs] def to_quadratic_program(self) -> QuadraticProgram: """Convert an SK model problem instance into a :class:`~qiskit_optimization.problems.QuadraticProgram`. Returns: The :class:`~qiskit_optimization.problems.QuadraticProgram` created from the SK problem instance. """ mdl = Model(name="SK-model") x = mdl.binary_var_list(self._graph.number_of_nodes()) objective = mdl.sum( -1 / np.sqrt(self._num_sites) * self._graph.edges[i, j]["weight"] * (2 * x[i] - 1) * (2 * x[j] - 1) for i, j in self._graph.edges ) # we converted the standard H(x)=-1/\sqrt{n} \sum w_{ij}x_ix_j, where x_i\in\pm 1 to binary. mdl.minimize(objective) return from_docplex_mp(mdl)
[docs] def interpret(self, result: OptimizationResult | np.ndarray) -> list[int]: """Interpret a result as configuration of spins. Args: result : The calculated result of the problem. Returns: configuration of spins """ configuration = [2 * x - 1 for x in self._result_to_x(result)] return configuration
@property def graph(self) -> nx.Graph: """Getter of the graph representation. Returns: A graph for a problem. """ return self._graph @property def num_sites(self) -> int: """Getter of the number of sites. Returns: Number of sites. """ return self._num_sites