ommx_openjij_adapter#

Submodules#

Classes#

OMMXOpenJijSAAdapter

Sample optimization candidates with OpenJij simulated annealing.

Functions#

decode_to_samples(response) → ommx.Samples

Convert openjij.Response to ommx.Samples

Package Contents#

class OMMXOpenJijSAAdapter(ommx_instance: Instance, *, beta_min: float | None = None, beta_max: float | None = None, num_sweeps: int | None = None, num_reads: int | None = None, schedule: list | None = None, initial_state: list | dict | None = None, updater: str | None = None, sparse: bool | None = None, reinitialize_state: bool | None = None, seed: int | None = None)#

Sample optimization candidates with OpenJij simulated annealing.

Install ommx-openjij-adapter alongside a compatible OMMX SDK. The example below needs no other Adapter, external data, or earlier Notebook state. INPUT_CLASS describes the exact input accepted by the constructor and preparation-free methods: used decision variables must be Binary, the objective must be a polynomial minimization, and no regular or special constraints may remain active. Polynomial degree is not limited to two: OpenJij’s QUBO and Binary-HUBO paths are supported.

sample() returns an evaluated ommx.SampleSet; solve() selects its best feasible candidate as a ommx.Solution. Both easy paths prepare an isolated copy with a fresh recommended policy. To choose a penalty weight, prepare an Instance explicitly and call sample_without_preparation() or solve_without_preparation().

Build a problem and choose its penalty weight

Choose exactly one of two options and maximize its score. A OneHot constraint expresses that exactly one of the Binary variables is one:

>>> import copy
>>> from ommx import FixedPenaltyPreparation, Instance, OneHotConstraint, Sense
>>> from ommx_openjij_adapter import OMMXOpenJijSAAdapter
>>> source = Instance.maximize()
>>> x = [source.new_binary("x", subscripts=[i]) for i in range(2)]
>>> source.objective = 3 * x[0] + 2 * x[1]
>>> _ = source.add_one_hot_constraint(OneHotConstraint(variables=x))
>>> target = OMMXOpenJijSAAdapter.INPUT_CLASS
>>> target.contains(source)
False

The source is a constrained maximization, so it is not a direct OpenJij input. Take the Adapter’s recommended policy and add an application-chosen penalty weight. The recommendation deliberately leaves that weight unset. ommx.Instance.prepare() changes its receiver in place; retain a copy of the source when trying different choices:

>>> prepared = copy.copy(source)
>>> policy = OMMXOpenJijSAAdapter.recommended_preparation_policy()
>>> policy.fixed_penalty = (
...     FixedPenaltyPreparation.uniform_penalty_method_with_fixed_weight(weight=4.0)
... )
>>> prepared.prepare(target, policy)
>>> target.contains(prepared)
True
>>> assert not target.contains(source)

Here preparation lowers OneHot to an equality, changes maximization to minimization, and penalizes the equality violation with weight 4. Choosing both options gains two points over choosing the first alone, but incurs a penalty of four. This weight is suitable for this small example; it is not a general recipe for choosing sufficient penalties. See ommx.FixedPenaltyPreparation.uniform_penalty_method_with_fixed_weight() for the exact penalty contract, including its treatment of inequalities.

Reaching INPUT_CLASS establishes the representation accepted by OpenJij. It does not guarantee that sampling will find a feasible candidate or prove optimality for the original problem. To change the weight, prepare a new copy of source. Changing policy and preparing the already applicable prepared object does not replace the penalty already stored.

Sample and read evaluated candidates

Pass the explicitly prepared input to the preparation-free method. num_reads is the number of sampling trials; seed controls the sampler’s random input. The candidate distribution can vary with the backend version and execution environment:

>>> sample_set = OMMXOpenJijSAAdapter.sample_without_preparation(
...     prepared, num_reads=10, seed=42
... )
>>> summary = sample_set.summary
>>> assert len(summary) == 10
>>> assert sample_set.sense == Sense.Maximize

Inspect summary to see one row per sample_id, with objective and feasible columns. Different IDs may have identical assignments. Feasible candidates appear first, then the reported objective orders each feasibility group according to the problem’s reporting sense. In this example, the reported objective is the original score 3*x[0] + 2*x[1] and larger is better. Feasibility includes the retained OneHot condition, even though OpenJij receives no active constraints.

The table is not raw OpenJij energy: sense conversion, penalties, and a constant omitted from the sampler coefficients can make the search energy differ from the reported objective. Decoding evaluates candidates through the prepared Instance, including its retained evaluation information. extract_decision_variables("x") selects variables named x; dictionary keys (0,) and (1,) are the subscripts assigned while modeling:

>>> for sample_id in sample_set.sample_ids():
...     candidate = sample_set.get(sample_id)
...     values = candidate.extract_decision_variables("x")
...     assert candidate.objective == 3 * values[(0,)] + 2 * values[(1,)]
...     assert candidate.feasible == (sum(values.values()) == 1)

Select among the obtained feasible candidates

ommx.SampleSet.best_feasible selects by the reported objective among the feasible candidates actually obtained. The names and subscripts set while modeling identify the selected values:

>>> solution = sample_set.best_feasible
>>> selected = solution.extract_decision_variables("x")
>>> assert solution.feasible and sum(selected.values()) == 1
>>> assert solution.objective == 3 * selected[(0,)] + 2 * selected[(1,)]
>>> details = solution.decision_variables_df()[["name", "subscripts", "value"]]

This selection is not a global optimality certificate. If no sampled candidate is feasible, best_feasible raises ValueError. Inspect the feasibility column and reconsider the model, weight, or sampling settings. solve_without_preparation() performs the same sampling and selection in one call and can raise the same error; use the sampling path when you need the unsuccessful candidates too.

Calling sample() or solve() obtains a new recommended policy; neither accepts the edited policy above. Explicit preparation followed by a preparation-free method keeps the application’s penalty choice. The ommx.SampleSet Reference explains result inspection and selection in full. For an independent application, see the TSP sampling example.

classmethod check_applicability(ommx_instance: Instance) → InstanceClassMembershipReport#

Check INPUT_CLASS membership without mutation.

decode(data: openjij.Response) → Solution#

Decode sampler output and return its best feasible solution.

decode_to_samples(data: openjij.Response) → Samples#

Convert openjij.Response to ommx.Samples

There is a static method decode_to_samples() that does the same thing.

decode_to_sampleset(data: openjij.Response) → SampleSet#
classmethod recommended_preparation_policy() → PreparationPolicy#

Recommend the model changes commonly needed by OpenJij.

The recommendation lowers every special-constraint family, converts the active objective to minimization, adds Integer slack while permitting an inequality to remain when exact equality conversion is unavailable, and log-encodes every used Integer variable. Both Integer slack ranges use 32.

Fixed penalty magnitudes remain explicit caller parameters because sufficient values depend on the application. The shared Instance owner operation validates their nonnegative-with-tolerance domain. Set fixed_penalty on the fresh returned policy when active constraints must be removed.

classmethod require_applicable(ommx_instance: Instance) → InstanceClassMembershipReport#

Return the membership report or raise AdapterNotApplicableError.

classmethod sample(ommx_instance: Instance, *, beta_min: float | None = None, beta_max: float | None = None, num_sweeps: int | None = None, num_reads: int | None = None, schedule: list | None = None, updater: str | None = None, sparse: bool | None = None, reinitialize_state: bool | None = None, seed: int | None = None, diagnostics: DiagnosticsSink | None = None) → SampleSet#

Prepare and sample an isolated copy of ommx_instance.

This obtains a fresh recommended policy. For a complete example with an explicit penalty weight, see ommx_openjij_adapter.OMMXOpenJijSAAdapter.

OpenJij initial_state values are defined against the solver-variable representation of an exact Adapter input, so they are accepted only by sample_without_preparation().

classmethod sample_without_preparation(ommx_instance: Instance, *, beta_min: float | None = None, beta_max: float | None = None, num_sweeps: int | None = None, num_reads: int | None = None, schedule: list | None = None, initial_state: list | dict | None = None, updater: str | None = None, sparse: bool | None = None, reinitialize_state: bool | None = None, seed: int | None = None, diagnostics: DiagnosticsSink | None = None) → SampleSet#

Sample an exact OpenJij Adapter input without preparing it.

See ommx_openjij_adapter.OMMXOpenJijSAAdapter for a complete example from an explicitly prepared constrained model to candidate evaluation and selection.

initial_state is defined against this exact input’s solver-variable representation.

classmethod solve(ommx_instance: Instance, *, beta_min: float | None = None, beta_max: float | None = None, num_sweeps: int | None = None, num_reads: int | None = None, schedule: list | None = None, updater: str | None = None, sparse: bool | None = None, reinitialize_state: bool | None = None, seed: int | None = None, diagnostics: DiagnosticsSink | None = None) → Solution#

Prepare, sample, and return the best feasible result.

Selects from the obtained candidates and does not prove optimality. Raises ValueError if no sampled candidate is feasible. Use sample() to retain all candidates for inspection.

OpenJij initial_state values are defined against the solver-variable representation of an exact Adapter input, so they are accepted only by solve_without_preparation().

classmethod solve_without_preparation(ommx_instance: Instance, *, beta_min: float | None = None, beta_max: float | None = None, num_sweeps: int | None = None, num_reads: int | None = None, schedule: list | None = None, initial_state: list | dict | None = None, updater: str | None = None, sparse: bool | None = None, reinitialize_state: bool | None = None, seed: int | None = None, diagnostics: DiagnosticsSink | None = None) → Solution#

Return the best feasible result from sample_without_preparation().

Selection uses the reported objective and retained feasibility checks. It does not prove optimality and raises ValueError when no feasible candidate was obtained. Use sample_without_preparation() to inspect all candidates, as shown in ommx_openjij_adapter.OMMXOpenJijSAAdapter.

initial_state is defined against the exact Adapter input’s solver-variable representation.

INPUT_CLASS: ClassVar[InstanceClass]#

Required condition for an exact Adapter input.

MAX_OPENJIJ_VARIABLE_ID: ClassVar[int] = 9223372036854775807#
beta_max: float | None = None#

maximum value of inverse temperature

beta_min: float | None = None#

minimal value of inverse temperature

initial_state: list | dict | None = None#

initial state (parameter only used if problem is QUBO)

num_reads: int | None = None#

number of reads

num_sweeps: int | None = None#

number of sweeps

ommx_instance: Instance#

Isolated copy of the exact Adapter input used to evaluate returned samples.

reinitialize_state: bool | None = None#

if true reinitialize state for each run (parameter only used if problem is QUBO)

property sampler_input: dict[tuple[int, ...], float]#
schedule: list | None = None#

list of inverse temperature (parameter only used if problem is QUBO)

seed: int | None = None#

seed for Monte Carlo algorithm

property solver_input: dict[tuple[int, ...], float]#

Expose sampler_input through the SolverAdapter interface.

sparse: bool | None = None#

use sparse matrix or not (parameter only used if problem is QUBO)

updater: str | None = None#

updater algorithm

decode_to_samples(response: openjij.Response) → Samples#

Convert openjij.Response to ommx.Samples