ParametricInstance

ParametricInstance#

class ParametricInstance#
__copy__() → ParametricInstance#
__deepcopy__(_memo: Any) → ParametricInstance#
__repr__() → str#
__str__() → str#
add_constraint(constraint: Constraint) → AttachedConstraint#

Add a regular constraint to this parametric instance.

Picks an unused ConstraintID, drains the wrapper’s context snapshot into this parametric instance’s SoA store, and returns an AttachedConstraint bound to the new id. The input Constraint is not mutated; subsequent writes that should land on this parametric instance must go through the returned handle.

Raises ValueError if the constraint references an id that is neither a defined decision variable nor a defined parameter, or if it references an id currently used as a substitution-dependency key.

add_decision_variable(variable: DecisionVariable) → AttachedDecisionVariable#

Add a decision variable to this parametric instance. Returns an AttachedDecisionVariable bound to the variable’s id — a write-through handle for further label updates.

Raises ValueError if the variable’s id collides with an existing decision variable or parameter. Substituted variables retain their ids and therefore also count as existing decision variables.

add_indicator_constraint(constraint: IndicatorConstraint) → AttachedIndicatorConstraint#

Add an indicator constraint to this parametric instance.

Picks an unused IndicatorConstraintID, drains the wrapper’s context snapshot into this parametric instance’s SoA store, and returns an AttachedIndicatorConstraint bound to the new id.

Raises ValueError if the constraint references an id that is neither a defined decision variable nor a defined parameter, or if it references an id currently used as a substitution-dependency key.

add_one_hot_constraint(constraint: OneHotConstraint) → AttachedOneHotConstraint#

Add a one-hot constraint to this parametric instance.

add_sos1_constraint(constraint: Sos1Constraint) → AttachedSos1Constraint#

Add a SOS1 constraint to this parametric instance.

add_user_annotation(key: str, value: str, *, annotation_namespace: str = 'org.ommx.user.') → None#
add_user_annotations(annotations: Mapping[str, str], *, annotation_namespace: str = 'org.ommx.user.') → None#
attached_decision_variable(variable_id: int) → AttachedDecisionVariable#

Look up the AttachedDecisionVariable for the given id — a write-through handle.

constraint_context_df(*, kind: Literal["regular", "indicator", "one_hot", "sos1"]) → DataFrame#

Constraint context DataFrame (id-indexed). See ommx.Instance.constraint_context_df() for column / kind= semantics.

constraint_parameters_df(*, kind: Literal["regular", "indicator", "one_hot", "sos1"]) → DataFrame#

Constraint parameters DataFrame (long format).

constraint_provenance_df(*, kind: Literal["regular", "indicator", "one_hot", "sos1"]) → DataFrame#

Constraint provenance DataFrame (long format).

constraint_removed_reasons_df(*, kind: Literal["regular", "indicator", "one_hot", "sos1"]) → DataFrame#

Removed-constraint reasons DataFrame (long format).

constraints_df(*, kind: Literal["regular", "indicator", "one_hot", "sos1"], include: Optional[Sequence[str]] = None, removed: bool = False) → DataFrame#

DataFrame of constraints, dispatched on kind=. See ommx.Instance.constraints_df() for column / kind= / include= / removed= semantics.

decision_variables_df(include: Optional[Sequence[str]] = None) → DataFrame#

DataFrame of decision variables

display_function(function: ToFunction, max_terms: Optional[int] = 100, max_chars: Optional[int] = 20000) → FunctionDisplay#

Build a bounded notebook display object for a function in this parametric instance’s context.

By default this returns a preview capped at 100 complete terms and 20,000 characters. Use format_function() for an unbounded plain text string.

empty() → ParametricInstance#

Create trivial empty instance of minimization with zero objective, no constraints, and no decision variables and parameters.

extract_constraints(name: str) → dict[tuple[int, ...], ConstraintView]#

Extract active constraints of every family by name, keyed by subscript tuples.

Values are attached handles, just as in constraints: edits update this model. The returned dictionary snapshots the matching keys; it does not track later label or membership changes. Removed constraints are excluded. Parameters and descriptions do not participate in matching.

Raises KeyError if no active constraint has this name, and ValueError if matching constraints share subscripts, including across different families. Use typed-ID lookup in constraints to distinguish ambiguous labels.

format_function(function: ToFunction, max_terms: Optional[int] = None, max_chars: Optional[int] = None) → str#

Format a function using this parametric instance’s decision-variable and parameter labels.

The plain repr() / str() representation of Function remains context-free and renders raw x<id> symbols such as x1. Use this method when labels from this parametric instance should be used instead.

from_components(*, sense: Sense, objective: ToFunction, decision_variables: Sequence[DecisionVariable], constraints: Mapping[ConstraintID, Constraint] | Mapping[int, Constraint] | ConstraintID | int | Constraint, parameters: Sequence[Parameter], indicator_constraints: Mapping[IndicatorConstraintID, IndicatorConstraint] | Mapping[int, IndicatorConstraint] | IndicatorConstraintID | int | IndicatorConstraint = None, one_hot_constraints: Mapping[OneHotConstraintID, OneHotConstraint] | Mapping[int, OneHotConstraint] | OneHotConstraintID | int | OneHotConstraint = None, sos1_constraints: Mapping[Sos1ConstraintID, Sos1Constraint] | Mapping[int, Sos1Constraint] | Sos1ConstraintID | int | Sos1Constraint = None, named_functions: Optional[Sequence[NamedFunction]] = None, description: Optional[InstanceDescription] = None) → ParametricInstance#

Build a parametric instance from its model components.

Constraint mappings accept integer keys or IDs of the matching family. Integers are promoted to that family’s ID. IDs of another family raise TypeError; keys that become duplicates raise ValueError. Returned collections always use typed IDs.

Raises ValueError if a decision variable and parameter use the same ID.

from_v1_bytes(bytes: bytes) → ParametricInstance#

Deserialize a parametric instance from v1 protobuf bytes.

Raises ValueError if the protobuf payload is malformed or semantically invalid.

from_v2_bytes(bytes: bytes) → ParametricInstance#

Deserialize a parametric instance from v2 protobuf bytes.

Raises ValueError if the protobuf payload is malformed or semantically invalid.

get_decision_variable_by_id(variable_id: int) → DecisionVariable#

Get a specific decision variable by ID

get_named_function_by_id(named_function_id: int) → NamedFunction#

Get a specific named function by ID

get_parameter_by_id(parameter_id: int) → Parameter#

Get a specific parameter by ID

get_user_annotation(key: str, *, annotation_namespace: str = 'org.ommx.user.') → str#
get_user_annotations(*, annotation_namespace: str = 'org.ommx.user.') → dict[str, str]#
named_functions_df(include: Optional[Sequence[str]] = None) → DataFrame#

DataFrame of named functions

parameters_df(include: Optional[Sequence[str]] = None) → DataFrame#

DataFrame of parameters

replace_annotations(annotations: Mapping[str, str]) → None#
substitute(assignments: Mapping[int, ToFunction]) → None#

Substitute decision variables with function expressions (in-place).

Replaces each given decision variable with the provided function in the objective and all active constraints. Replacement functions may still reference parameters; those parameter references remain in this parametric instance and are evaluated later by with_parameters(). Assignment targets must be existing decision variable IDs. Replacement expressions may only reference existing decision variable or parameter IDs; parameter IDs cannot be assignment targets.

Args:

  • assignments: A dict mapping decision variable IDs to the function expressions that should replace them.

Important: This method performs an algebraic rewrite. It does not automatically translate the substituted variable’s bound or kind into constraints on the replacement expression. If the substitution must preserve the optimization problem, the caller must provide a domain-preserving encoding or add the required linking and bound constraints explicitly.

Raises ValueError on cyclic or recursive assignments, undefined IDs, when a parameter ID is used as an assignment target, or when substituting a variable that is a member of an indicator, one-hot, or SOS1 constraint.

Postconditions#

Substitution rewrites active expressions while materialized output evaluation restores the substituted variable.

>>> from ommx import DecisionVariable, Instance, Sense
>>> x = DecisionVariable.binary(0)
>>> b = DecisionVariable.binary(1)
>>> source = Instance.from_components(
...     decision_variables=[x, b], objective=x, constraints={}, sense=Sense.Maximize
... )
>>> assert source.convert_active_objective(Sense.Minimize)
>>> parametric = source.as_parametric_instance()
>>> parametric.substitute({0: b})
>>> materialized = parametric.with_parameters({})
>>> assert materialized.required_ids() == {1}
>>> assert materialized.objective.evaluate({1: 1}) == -1.0
>>> solution = materialized.evaluate({1: 1})
>>> assert (solution.sense, solution.objective) == (Sense.Maximize, 1.0)
to_v1_bytes() → bytes#

Serialize this parametric instance in the OMMX v1 wire format.

Errors#

Serialization raises RuntimeError whenever an output objective is present because v1 cannot represent it.

>>> from ommx import DecisionVariable, Instance, Sense
>>> x = DecisionVariable.binary(0)
>>> instance = Instance.from_components(
...     decision_variables=[x], objective=x, constraints={}, sense=Sense.Maximize
... )
>>> assert instance.convert_active_objective(Sense.Minimize)
>>> assert instance.convert_active_objective(Sense.Maximize)
>>> parametric = instance.as_parametric_instance()
>>> try:
...     parametric.to_v1_bytes()
... except RuntimeError:
...     pass
... else:
...     raise AssertionError("v1 serialization accepted an output objective")
to_v2_bytes() → bytes#

Serialize this parametric instance in the OMMX v2 wire format.

Postconditions#

A v2 round-trip preserves both active and output objective semantics through materialization.

>>> from ommx import DecisionVariable, Instance, ParametricInstance, Sense
>>> x = DecisionVariable.binary(0)
>>> source = Instance.from_components(
...     decision_variables=[x], objective=x, constraints={7: x == 1}, sense=Sense.Minimize
... )
>>> parametric = source.uniform_penalty_method()
>>> parameter_id = parametric.parameters[0].id
>>> restored = ParametricInstance.from_v2_bytes(parametric.to_v2_bytes())
>>> materialized = restored.with_parameters({parameter_id: 2.0})
>>> assert materialized.sense == Sense.Minimize
>>> assert materialized.objective.evaluate({0: 0}) == 2.0
>>> solution = materialized.evaluate({0: 0})
>>> assert (solution.sense, solution.objective) == (Sense.Minimize, 0.0)
variable_labels_df() → DataFrame#

Decision-variable modeling-label DataFrame (id-indexed).

variable_parameters_df() → DataFrame#

Decision-variable parameters DataFrame (long format).

with_parameters(parameters: Mapping[int, float]) → Instance#

Substitute parameters to yield an instance.

Provide a dict mapping every declared parameter ID to its numerical value, including parameters not referenced by an expression. The original ParametricInstance is unchanged and can be materialized again. Missing declared IDs raise RuntimeError.

The method checks that declared IDs are included, not that the key sets are equal. Additional keys are accepted and participate in substitution wherever referenced. In particular, an extra decision-variable ID can also substitute that coordinate in expressions. For parameter-only materialization, supply exactly the IDs listed by parameters.

Substitution uses the SDK’s default absolute tolerance and the expression partial-evaluation rules; see partial_evaluate(). This is not a feasibility check or decision-variable kind/bound validation. There is no blanket finiteness check of all supplied values: a referenced non-finite value can fail during substitution, while an unreferenced value need not be examined. Successful materialization does not prove that all supplied values are finite or that the resulting problem is feasible.

>>> from ommx import DecisionVariable, Parameter, ParametricInstance, Sense
>>> x = DecisionVariable.binary(0)
>>> p, unused = Parameter(1, name="p"), Parameter(2, name="unused")
>>> family = ParametricInstance.from_components(
...     decision_variables=[x], parameters=[p, unused], objective=x + p,
...     constraints={}, sense=Sense.Minimize
... )
>>> try:
...     family.with_parameters({p.id: 3})
... except RuntimeError as error:
...     assert "Missing parameters" in str(error)
... else:
...     raise AssertionError("an omitted declared parameter was accepted")
>>> concrete = family.with_parameters({p.id: 3, unused.id: 0})
>>> assert concrete.objective.evaluate({x.id: 1}) == 4.0

Postconditions#

Penalty conversion preserves existing output semantics, or captures the pre-penalty active objective when no output objective exists. Materialization substitutes parameters in the active energy, and an existing output objective remains explicit even if specialization makes it structurally equal to the active objective.

>>> from ommx import DecisionVariable, Instance, Sense
>>> x = DecisionVariable.binary(0)
>>> source = Instance.from_components(
...     decision_variables=[x], objective=x, constraints={7: x == 1}, sense=Sense.Minimize
... )
>>> parametric = source.uniform_penalty_method()
>>> parameter_id = parametric.parameters[0].id
>>> materialized = parametric.with_parameters({parameter_id: 2.0})
>>> assert materialized.objective.evaluate({0: 0}) == 2.0
>>> solution = materialized.evaluate({0: 0})
>>> assert (solution.sense, solution.objective, solution.feasible) == (Sense.Minimize, 0.0, False)
property annotations: MappingProxyType[str, str]#

Read-only property.

Returns a read-only mapping of flat annotations.

Use add_user_annotation(), metadata properties, or replace_annotations() to modify annotations.

property authors: list[str]#
property constraint_names: set[str]#

Read-only property.

Unique names across all constraint families, as a set of strings.

Only active constraints are included. The scope matches extract_constraints. Unnamed constraints are excluded; an explicitly empty name is included. Duplicate names appear once, even when extraction would reject duplicate subscripts. Each access returns a fresh set; editing it does not change this owner.

property constraints: ConstraintCollection#

Read-only property.

Live mapping of all active constraint families, keyed by typed IDs. The view retains this owner and fetches each constraint on demand.

property created: Optional[datetime]#
property dataset: Optional[str]#
property decision_variable_ids: set[int]#

Read-only property.

property decision_variable_names: set[str]#

Read-only property.

Unique decision-variable names as a set of strings, excluding parameters. Unnamed variables are excluded; explicitly empty names are included. Each access returns a fresh set; editing it does not change this owner.

property decision_variables: list[AttachedDecisionVariable]#

Read-only property.

List of all decision variables in the parametric instance sorted by their IDs.

Returns a list of AttachedDecisionVariable write-through handles. See decision_variables for the same shape on Instance.

property description: Optional[InstanceDescription]#

Read-only property.

property license: Optional[str]#
property named_functions: list[NamedFunction]#

Read-only property.

property num_constraints: Optional[int]#

Read-only property.

property num_variables: Optional[int]#

Read-only property.

property objective: Function#

Read-only property.

property output_objective: Optional[OutputObjective]#

Read-only property.

Read-only output objective retained through parameter materialization, if one has been captured.

Postconditions#

Conversion preserves both absence and an explicit output objective equal to the active pair.

>>> from ommx import DecisionVariable, Instance, Sense
>>> x = DecisionVariable.binary(0)
>>> source = Instance.from_components(
...     decision_variables=[x], objective=x, constraints={}, sense=Sense.Maximize
... )
>>> assert source.as_parametric_instance().output_objective is None
>>> assert source.convert_active_objective(Sense.Minimize)
>>> assert source.convert_active_objective(Sense.Maximize)
>>> parametric = source.as_parametric_instance()
>>> output = parametric.output_objective
>>> assert output is not None
>>> assert output.sense == parametric.sense
>>> assert output.function.almost_equal(parametric.objective)
property parameter_ids: set[int]#

Read-only property.

property parameters: list[Parameter]#

Read-only property.

property removed_constraints: RemovedConstraintCollection#

Read-only property.

Live mapping of all removed constraint families, keyed by typed IDs. The view retains this owner and fetches each constraint on demand.

property sense: Sense#

Read-only property.

property title: Optional[str]#