ommx.adapter
============

.. py:module:: ommx.adapter


Attributes
----------

.. autoapisummary::

   ommx.adapter.SamplerInput
   ommx.adapter.SamplerOutput
   ommx.adapter.SolverInput
   ommx.adapter.SolverOutput


Exceptions
----------

.. autoapisummary::

   ommx.adapter.AdapterNotApplicableError
   ommx.adapter.NoSolutionReturned
   ommx.adapter.UnboundedDetected


Classes
-------

.. autoapisummary::

   ommx.adapter.DiagnosticReport
   ommx.adapter.DiagnosticsSink
   ommx.adapter.SamplerAdapter
   ommx.adapter.SolverAdapter


Module Contents
---------------

.. py:exception:: AdapterNotApplicableError(adapter: str, report: ommx.InstanceClassMembershipReport)



   Raised when an instance is not applicable to an adapter.


   .. py:attribute:: adapter
      :type:  str


   .. py:attribute:: report
      :type:  ommx.InstanceClassMembershipReport


.. py:exception:: NoSolutionReturned



   Raised when no solution was returned.

   This indicates that the solver did not return any solution (whether feasible
   or not) (e.g., due to time limits).
   This does not prove that the mathematical model itself is infeasible.


.. py:exception:: UnboundedDetected



   Raised when the problem is proven to be unbounded.

   This corresponds to ``Optimality.OPTIMALITY_UNBOUNDED`` and indicates that
   the mathematical model itself is unbounded.
   Should not be used when unboundedness cannot be proven (e.g., heuristic solvers).


.. py:class:: DiagnosticReport



   Adapter diagnostic report convertible with ``dataclasses.asdict``.


.. py:class:: DiagnosticsSink



   Receiver for adapter-defined diagnostics emitted during a solve.

   Adapters may call ``record`` while the backend solver is still running,
   including from backend callbacks. Sink implementations should keep
   ``record`` append-only, defer validation or serialization until after the
   solve, and preserve the order in which diagnostics are received.

   A conforming sink must not raise from ``record``. If recording fails, the
   sink should log the failure and return normally. If ``record`` does raise,
   that is a sink contract violation; adapters may let the exception propagate
   and do not need to recover from it.


   .. py:method:: record(diagnostic: DiagnosticReport) -> None

      Record one adapter-defined dataclass diagnostic report or event.

      This method must not raise under normal sink failures. Custom sinks
      should log failures and return instead.



.. py:class:: SamplerAdapter



   An abstract interface for OMMX Sampler Adapters, defining how samplers should be used with OMMX.

   See the `Adapter implementation tutorial <https://jij-inc-ommx.readthedocs-hosted.com/en/latest/tutorial/implement_adapter.html>`_
   for the complete implementation contract and reference implementations.

   The exact-input, easy-API preparation, strict preparation-free API, and
   used-variable contracts of :class:`SolverAdapter` also apply to sampler
   adapters. A sampler whose
   backend labels are the OMMX variable IDs may preserve that identity directly;
   other representations need an explicit correspondence. In either case, each
   decoded sample must contain a value for every variable in
   ``ommx_instance.used_decision_variables`` before ``evaluate_samples`` is
   called against an unchanged :class:`ommx.Instance` snapshot mathematically
   identical to the encoded exact input. Backend formats that omit a
   zero-interaction variable therefore need an adapter-owned decoding default
   consistent with that format.


   .. py:method:: check_applicability(ommx_instance: ommx.Instance) -> ommx.InstanceClassMembershipReport
      :classmethod:


      Check ``INPUT_CLASS`` membership without mutation.



   .. py:method:: decode(data: SolverOutput) -> ommx.Solution

      Decode sampler output and return its best feasible solution.



   .. py:method:: decode_to_sampleset(data: SamplerOutput) -> ommx.SampleSet
      :abstractmethod:



   .. py:method:: recommended_preparation_policy() -> ommx.PreparationPolicy
      :classmethod:


      Return a fresh policy recommended for this Adapter's ``INPUT_CLASS``.

      The easy APIs apply it to an isolated copy. Advanced callers may edit
      and apply it explicitly before using a preparation-free API. This
      method itself neither prepares an instance nor guarantees
      applicability. The default policy is empty.



   .. py:method:: require_applicable(ommx_instance: ommx.Instance) -> ommx.InstanceClassMembershipReport
      :classmethod:


      Return the membership report or raise ``AdapterNotApplicableError``.



   .. py:method:: sample(ommx_instance: ommx.Instance, *, diagnostics: DiagnosticsSink | None = None) -> ommx.SampleSet
      :classmethod:


      Prepare and sample an isolated copy of an OMMX instance.

      The input ``ommx_instance`` is never modified. The copy is prepared for
      ``INPUT_CLASS`` with :meth:`recommended_preparation_policy`, then passed
      to :meth:`sample_without_preparation`.

      ``Run.log_sample`` owns the reserved ``diagnostics`` keyword and uses
      it the same way as ``Run.log_solve``. ``None`` means diagnostics are
      disabled.



   .. py:method:: sample_without_preparation(ommx_instance: ommx.Instance, *, diagnostics: DiagnosticsSink | None = None) -> ommx.SampleSet
      :classmethod:

      :abstractmethod:


      Sample an exact Adapter input without running ``Instance.prepare``.

      ``ommx_instance`` must belong to ``INPUT_CLASS``. Implementations must
      reject non-members with :class:`AdapterNotApplicableError` and must not
      prepare or otherwise modify the input instance.



   .. py:method:: solve(ommx_instance: ommx.Instance, *, diagnostics: DiagnosticsSink | None = None) -> ommx.Solution
      :classmethod:


      Prepare and solve an isolated copy of an OMMX instance.

      The input ``ommx_instance`` is never modified. The copy is prepared for
      ``INPUT_CLASS`` with :meth:`recommended_preparation_policy`, then passed
      to :meth:`solve_without_preparation`.

      ``Run.log_solve`` owns the reserved ``diagnostics`` keyword. When
      called with ``store_diagnostics=True``, it passes a sink to the adapter
      and stores recorded diagnostics with the Solve entry. Adapters may
      record adapter-defined dataclass diagnostics into the sink during the
      solve; ``None`` means diagnostics are disabled. Adapters do not need to
      catch exceptions raised by a non-conforming diagnostics sink.



   .. py:method:: solve_without_preparation(ommx_instance: ommx.Instance, *, diagnostics: DiagnosticsSink | None = None) -> ommx.Solution
      :classmethod:


      Return the best feasible result from :meth:`sample_without_preparation`.



   .. py:attribute:: INPUT_CLASS
      :type:  ClassVar[ommx.InstanceClass]

      Required condition for an exact Adapter input.



   .. py:property:: sampler_input
      :type: SamplerInput

      :abstractmethod:



   .. py:property:: solver_input
      :type: SolverInput


      Expose :attr:`sampler_input` through the SolverAdapter interface.



.. py:class:: SolverAdapter



   An abstract interface for OMMX Solver Adapters, defining how solvers should be used with OMMX.

   See the `Adapter implementation tutorial <https://jij-inc-ommx.readthedocs-hosted.com/en/latest/tutorial/implement_adapter.html>`_
   for the complete implementation contract and reference implementation.

   Subclasses declare ``INPUT_CLASS`` as the OMMX-defined structural class of
   exact inputs they can encode. Membership in that class is the complete
   applicability condition: ``check_applicability`` only checks membership and
   does not mutate the input. A subclass should call ``require_applicable``
   before constructing backend input.

   The easy :meth:`solve` API prepares an isolated copy with the Adapter's
   recommended policy. Use :meth:`solve_without_preparation` when the caller
   has prepared an exact input explicitly and wants the Adapter to require
   ``INPUT_CLASS`` membership without applying preparation.

   When encoding OMMX decision variables, use
   ``ommx_instance.used_decision_variables`` rather than the complete decision
   variable table. Backend-only auxiliary variables may be added separately.
   Preserve the correspondence between each used OMMX variable ID and its
   backend representation. Decoding must recover a value for every used OMMX
   variable, construct a :class:`ommx.State`, and evaluate it against an
   unchanged :class:`ommx.Instance` snapshot that is mathematically identical
   to the exact input encoded for the backend. The Instance owns population of
   fixed, dependent, and irrelevant variables and construction of the final
   :class:`ommx.Solution`.


   .. py:method:: check_applicability(ommx_instance: ommx.Instance) -> ommx.InstanceClassMembershipReport
      :classmethod:


      Check ``INPUT_CLASS`` membership without mutation.



   .. py:method:: decode(data: SolverOutput) -> ommx.Solution
      :abstractmethod:



   .. py:method:: recommended_preparation_policy() -> ommx.PreparationPolicy
      :classmethod:


      Return a fresh policy recommended for this Adapter's ``INPUT_CLASS``.

      The easy APIs apply it to an isolated copy. Advanced callers may edit
      and apply it explicitly before using a preparation-free API. This
      method itself neither prepares an instance nor guarantees
      applicability. The default policy is empty.



   .. py:method:: require_applicable(ommx_instance: ommx.Instance) -> ommx.InstanceClassMembershipReport
      :classmethod:


      Return the membership report or raise ``AdapterNotApplicableError``.



   .. py:method:: solve(ommx_instance: ommx.Instance, *, diagnostics: DiagnosticsSink | None = None) -> ommx.Solution
      :classmethod:


      Prepare and solve an isolated copy of an OMMX instance.

      The input ``ommx_instance`` is never modified. The copy is prepared for
      ``INPUT_CLASS`` with :meth:`recommended_preparation_policy`, then passed
      to :meth:`solve_without_preparation`.

      ``Run.log_solve`` owns the reserved ``diagnostics`` keyword. When
      called with ``store_diagnostics=True``, it passes a sink to the adapter
      and stores recorded diagnostics with the Solve entry. Adapters may
      record adapter-defined dataclass diagnostics into the sink during the
      solve; ``None`` means diagnostics are disabled. Adapters do not need to
      catch exceptions raised by a non-conforming diagnostics sink.



   .. py:method:: solve_without_preparation(ommx_instance: ommx.Instance, *, diagnostics: DiagnosticsSink | None = None) -> ommx.Solution
      :classmethod:

      :abstractmethod:


      Solve an exact Adapter input without running ``Instance.prepare``.

      ``ommx_instance`` must belong to ``INPUT_CLASS``. Implementations must
      reject non-members with :class:`AdapterNotApplicableError` and must not
      prepare or otherwise modify the input instance.



   .. py:attribute:: INPUT_CLASS
      :type:  ClassVar[ommx.InstanceClass]

      Required condition for an exact Adapter input.



   .. py:property:: solver_input
      :type: SolverInput

      :abstractmethod:



.. py:data:: SamplerInput

.. py:data:: SamplerOutput

.. py:data:: SolverInput

.. py:data:: SolverOutput

