ommx.v1.ParametricInstance

ommx.v1.ParametricInstance#

ommx.v1.ParametricInstance is a class that represents mathematical models similar to ommx.v1.Instance. It also supports parameters (via ommx.v1.Parameter) in addition to decision variables. By assigning values to these parameters, you can create an ommx.v1.Instance. Because the resulting ommx.v1.Instance keeps the IDs of decision variables and constraints from ommx.v1.ParametricInstance, it is helpful when you need to handle a series of models where only some coefficients of the objective function or constraints change.

Consider the following knapsack problem.

\[\begin{split} \begin{align*} \text{maximize} \quad & \sum_{i=1}^{N} p_i x_i \\ \text{subject to} \quad & \sum_{i=1}^{N} w_i x_i \leq W \\ & x_i \in \{0, 1\} \quad (i=1, 2, \ldots, N) \end{align*} \end{split}\]

Here, \(N\) is the number of items, \(p_i\) is the value of item i, \(w_i\) is the weight of item i, and \(W\) is the knapsack’s capacity. The variable \(x_i\) is binary and indicates whether item i is included in the knapsack. In ommx.v1.Instance, fixed values were used for \(p_i\) and \(w_i\), but here they are treated as parameters.

from ommx.v1 import ParametricInstance, DecisionVariable, Parameter, Instance

N = 6
x = [DecisionVariable.binary(id=i, name="x", subscripts=[i]) for i in range(N)]

p = [Parameter.new(id=i+  N, name="Profit", subscripts=[i]) for i in range(N)]
w = [Parameter.new(id=i+2*N, name="Weight", subscripts=[i]) for i in range(N)]
W =  Parameter.new(id=  3*N, name="Capacity")

ommx.v1.Parameter also has an ID and uses the same numbering as ommx.v1.DecisionVariable, so please ensure there are no duplicates. Like decision variables, parameters can have names and subscripts. They can also be used with operators such as + and <= to create ommx.v1.Function or ommx.v1.Constraint objects.

objective = sum(p[i] * x[i] for i in range(N))
constraint = sum(w[i] * x[i] for i in range(N)) <= W

Now let’s combine these elements into an ommx.v1.ParametricInstance that represents the knapsack problem.

parametric_instance = ParametricInstance.from_components(
    decision_variables=x,
    parameters=p + w + [W],
    objective=objective,
    constraints=[constraint],
    sense=Instance.MAXIMIZE,
)

Like ommx.v1.Instance, you can view the decision variables and constraints as DataFrames through the decision_variables and constraints properties. In addition, ommx.v1.ParametricInstance has a parameters property for viewing parameter information in a DataFrame.

parametric_instance.parameters
[Parameter(raw=id: 6
 name: "Profit"
 subscripts: 0
 ),
 Parameter(raw=id: 7
 name: "Profit"
 subscripts: 1
 ),
 Parameter(raw=id: 8
 name: "Profit"
 subscripts: 2
 ),
 Parameter(raw=id: 9
 name: "Profit"
 subscripts: 3
 ),
 Parameter(raw=id: 10
 name: "Profit"
 subscripts: 4
 ),
 Parameter(raw=id: 11
 name: "Profit"
 subscripts: 5
 ),
 Parameter(raw=id: 12
 name: "Weight"
 subscripts: 0
 ),
 Parameter(raw=id: 13
 name: "Weight"
 subscripts: 1
 ),
 Parameter(raw=id: 14
 name: "Weight"
 subscripts: 2
 ),
 Parameter(raw=id: 15
 name: "Weight"
 subscripts: 3
 ),
 Parameter(raw=id: 16
 name: "Weight"
 subscripts: 4
 ),
 Parameter(raw=id: 17
 name: "Weight"
 subscripts: 5
 ),
 Parameter(raw=id: 18
 name: "Capacity"
 )]

Next, let’s assign specific values to the parameters. Use ParametricInstance.with_parameters, which takes a dictionary mapping each ommx.v1.Parameter ID to its corresponding value.

p_values = { x.id: value for x, value in zip(p, [10, 13, 18, 31, 7, 15]) }
w_values = { x.id: value for x, value in zip(w, [11, 15, 20, 35, 10, 33]) }
W_value = { W.id: 47 }

instance = parametric_instance.with_parameters({**p_values, **w_values, **W_value})

Symbolic substitution with parameters#

ParametricInstance.substitute works like Instance.substitute, but the replacement expressions may also contain registered parameters. The parameter references remain symbolic in the ParametricInstance; they are evaluated later by ParametricInstance.with_parameters when an Instance is materialized. Parameter references in removed constraints are materialized at the same time.

The assignment target must be a decision variable. Substituting a parameter ID is rejected, and every ID used on the right-hand side must be registered as either a decision variable or a parameter.

As with Instance.substitute, this is an algebraic rewrite and does not add constraints that preserve the substituted variable’s kind, lower, or upper. Add those constraints explicitly when the transformation must preserve the optimization model. See the Instance user guide for the general substitution behavior.

Note

ommx.v1.ParametricInstance cannot handle parameters that change the number of decision variables or parameters (for example, a variable \(N\)). If you need this functionality, please use a more advanced modeler such as JijModeling.