PreparationPolicy#
- class PreparationPolicy#
Select optional transformations applied by
prepare().A policy stores choices and settings; constructing or editing it does not transform an Instance. The target
InstanceClassdescribes the required representation, this policy selects permitted operations, andInstance.prepare(input_class, policy)applies them to that Instance in place.Each property selects at most one phase. Properties may be combined freely, although owner-operation validation and target membership can still make a combination fail for a particular
Instance. A policy is not a list of operations that will always run: Preparation stops as soon as the whole target class is reached, including before the first phase if already satisfied. Seeprepare()for the complete execution example, phase ordering, early stopping, and mutation on failure.Defaults and explicit selection
A default policy selects no Preparation phase. Future phases also default to disabled. The following policy initially leaves every transformation unselected, then permits only lowering OneHot constraints to regular equalities:
>>> from ommx import ( ... PreparationPolicy, ... ConstraintKind, ... SpecialConstraintPreparation, ... ) >>> policy = PreparationPolicy() >>> assert ( ... policy.special_constraints, ... policy.objective, ... policy.integer_slack, ... policy.integer_encoding, ... policy.fixed_penalty, ... policy.binary_power_reduction, ... ) == (None, None, None, None, None, None) >>> policy.special_constraints = SpecialConstraintPreparation.lower_special_constraints( ... kinds={ConstraintKind.OneHot} ... ) >>> assert policy.integer_encoding is None >>> assert policy.fixed_penalty is None
The corresponding settings are
SpecialConstraintPreparation,ObjectivePreparation,IntegerSlackPreparation,IntegerEncodingPreparation,FixedPenaltyPreparation, andBinaryPowerPreparation. Unselected phases do not run. The application chooses permitted transformations, numerical tolerances, and penalty magnitudes; a target class alone does not decide them or prove the transformations preserve the desired mathematical guarantees.QUBO, HUBO, and Adapter policies
for_qubo()andfor_hubo()return fresh policies for their respective formatting targets. Creating either policy does not prepare a model. Their penalty defaults are documented choices, not a guarantee that an arbitrary problem’s desired candidate will be selected. In particular,uniform_penalty_method_with_fixed_weight()explains why squaring an inequality’s body differs from penalizing only its violation.The explicit path is to call
Instance.preparewith the target and chosen policy, then format the active objective if coefficients are needed. The complete QUBO example is inprepare(). The convenience methodsto_qubo()andto_hubo()perform both Preparation and coefficient formatting in place;as_qubo_formatandas_hubo_formatperform formatting alone.A generic QUBO/HUBO factory is separate from an Adapter’s
recommended_preparation_policy(). An Adapter can accept a different class or leave problem-specific choices to the application. For explicit policies followed by strict execution, seeSolverAdapterandSamplerAdapter.- __eq__(other: object, /) bool#
- __new__(*, special_constraints: Optional[SpecialConstraintPreparation] = None, objective: Optional[ObjectivePreparation] = None, integer_slack: Optional[IntegerSlackPreparation] = None, integer_encoding: Optional[IntegerEncodingPreparation] = None, fixed_penalty: Optional[FixedPenaltyPreparation] = None, binary_power_reduction: Optional[BinaryPowerPreparation] = None) PreparationPolicy#
- for_hubo(*, uniform_penalty_weight: Optional[float] = None, penalty_weights: Optional[Mapping[int, float]] = None, inequality_integer_slack_max_range: int = 31) PreparationPolicy#
Return a fresh policy for preparing an instance for HUBO formatting.
uniform_penalty_weightandpenalty_weightsoverride the default uniform penalty weight of 1.0 and are mutually exclusive. The keyed form must cover exactly the active regular constraints at the penalty phase.inequality_integer_slack_max_rangedefaults to 31 and configures both the exact Integer-slack range and the fallback slack upper bound. Unlikefor_qubo(), this policy leaves Binary-power reduction disabled because HUBO accepts arbitrary polynomial degree.Postconditions#
Each call returns a fresh complete HUBO policy with no Binary-power reduction and exact overrides.
>>> from ommx import ( ... FixedPenaltyPreparation, IntegerEncodingPreparation, ... IntegerSlackPreparation, ObjectivePreparation, ... PreparationPolicy, Sense, ConstraintKind, ... SpecialConstraintPreparation, ... ) >>> expected_special = SpecialConstraintPreparation.lower_special_constraints( ... kinds={ ... ConstraintKind.Indicator, ... ConstraintKind.OneHot, ... ConstraintKind.Sos1, ... } ... ) >>> first = PreparationPolicy.for_hubo(inequality_integer_slack_max_range=17) >>> second = PreparationPolicy.for_hubo(inequality_integer_slack_max_range=17) >>> assert first is not second >>> assert first.special_constraints == expected_special >>> assert first.objective == ObjectivePreparation(target=Sense.Minimize) >>> assert first.integer_slack == IntegerSlackPreparation(max_integer_range=17, slack_upper_bound=17) >>> assert first.integer_encoding == IntegerEncodingPreparation.log_encode_all_used_integers() >>> assert first.fixed_penalty == FixedPenaltyPreparation.uniform_penalty_method_with_fixed_weight(weight=1.0) >>> assert first.binary_power_reduction is None >>> first.fixed_penalty = None >>> assert second.fixed_penalty == FixedPenaltyPreparation.uniform_penalty_method_with_fixed_weight(weight=1.0) >>> uniform = PreparationPolicy.for_hubo(uniform_penalty_weight=4.0) >>> assert uniform.fixed_penalty == FixedPenaltyPreparation.uniform_penalty_method_with_fixed_weight(weight=4.0)
Errors#
Supplying uniform and keyed penalty weights together raises
ValueError.>>> try: ... PreparationPolicy.for_hubo(uniform_penalty_weight=1.0, penalty_weights={3: 2.0}) ... except ValueError as error: ... assert "Both uniform_penalty_weight" in str(error) ... else: ... raise AssertionError("mutually exclusive penalty options were accepted")
- for_qubo(*, uniform_penalty_weight: Optional[float] = None, penalty_weights: Optional[Mapping[int, float]] = None, inequality_integer_slack_max_range: int = 31) PreparationPolicy#
Return a fresh policy for preparing an instance for QUBO formatting.
uniform_penalty_weightandpenalty_weightsoverride the default uniform penalty weight of 1.0 and are mutually exclusive. The keyed form must cover exactly the active regular constraints at the penalty phase.inequality_integer_slack_max_rangedefaults to 31 and configures both the exact Integer-slack range and the fallback slack upper bound. This QUBO policy also reduces powers of Binary variables before checking the quadratic target.Postconditions#
Each call returns a fresh complete QUBO policy whose optional weights and slack range are applied exactly.
>>> from ommx import ( ... BinaryPowerPreparation, FixedPenaltyPreparation, ... IntegerEncodingPreparation, IntegerSlackPreparation, ... ObjectivePreparation, PreparationPolicy, Sense, ... ConstraintKind, SpecialConstraintPreparation, ... ) >>> expected_special = SpecialConstraintPreparation.lower_special_constraints( ... kinds={ ... ConstraintKind.Indicator, ... ConstraintKind.OneHot, ... ConstraintKind.Sos1, ... } ... ) >>> expected_penalty = FixedPenaltyPreparation.uniform_penalty_method_with_fixed_weight(weight=1.0) >>> first = PreparationPolicy.for_qubo(inequality_integer_slack_max_range=17) >>> second = PreparationPolicy.for_qubo(inequality_integer_slack_max_range=17) >>> assert first is not second >>> assert first.special_constraints == expected_special >>> assert first.objective == ObjectivePreparation(target=Sense.Minimize) >>> assert first.integer_slack == IntegerSlackPreparation(max_integer_range=17, slack_upper_bound=17) >>> assert first.integer_encoding == IntegerEncodingPreparation.log_encode_all_used_integers() >>> assert first.fixed_penalty == expected_penalty >>> assert first.binary_power_reduction == BinaryPowerPreparation() >>> first.fixed_penalty = None >>> first.binary_power_reduction = None >>> assert second.fixed_penalty == expected_penalty >>> assert second.binary_power_reduction == BinaryPowerPreparation() >>> keyed = PreparationPolicy.for_qubo(penalty_weights={3: 2.0}) >>> assert keyed.fixed_penalty == FixedPenaltyPreparation.penalty_method_with_fixed_weights(weights={3: 2.0})
Errors#
Supplying uniform and keyed penalty weights together raises
ValueError.>>> try: ... PreparationPolicy.for_qubo(uniform_penalty_weight=1.0, penalty_weights={3: 2.0}) ... except ValueError as error: ... assert "Both uniform_penalty_weight" in str(error) ... else: ... raise AssertionError("mutually exclusive penalty options were accepted")