ommx.v1.Solution#
OMMX has several structures that represent the solution of mathematical models.
Data Structure |
Description |
---|---|
Holds the solution value for the decision variable ID. The simplest representation of a solution. |
|
A representation of the solution intended to be human-readable. In addition to the values of the decision variables and the evaluation values of the constraints, it also holds metadata for the decision variables and constraints added to the |
Most solvers are software designed to solve mathematical models, so they return minimal information equivalent to ommx.v1.State
, but OMMX mainly handles ommx.v1.Solution
, which allows users to easily check the optimization results.
ommx.v1.Solution
is generated by passing ommx.v1.State
or equivalent dict[int, float]
to the ommx.v1.Instance.evaluate
method. Let’s consider the simple optimization problem we saw in the previous section again:
It is clear that this has a feasible solution \(x = 1, y = 0\).
from ommx.v1 import Instance, DecisionVariable
# Create a simple instance
x = DecisionVariable.binary(1, name='x')
y = DecisionVariable.binary(2, name='y')
instance = Instance.from_components(
decision_variables=[x, y],
objective=x + y,
constraints=[x * y == 0],
sense=Instance.MAXIMIZE
)
# Create a solution
solution = instance.evaluate({1: 1, 2: 0}) # x=1, y=0
The generated ommx.v1.Solution
inherits most of the information from the ommx.v1.Instance
. Let’s first look at the decision variables.
solution.decision_variables
kind | lower | upper | name | subscripts | description | substituted_value | value | |
---|---|---|---|---|---|---|---|---|
id | ||||||||
1 | binary | 0.0 | 1.0 | x | [] | <NA> | <NA> | 1.0 |
2 | binary | 0.0 | 1.0 | y | [] | <NA> | <NA> | 0.0 |
In addition to the required attributes—ID, kind
, lower
, and upper
-it also inherits metadata such as name
. Additionally, the value
stores which was assigned in evaluate
. Similarly, the evaluation value is added to the constraints as value
.
solution.constraints
equality | value | used_ids | name | subscripts | description | dual_variable | removed_reason | |
---|---|---|---|---|---|---|---|---|
id | ||||||||
0 | =0 | 0.0 | {1, 2} | <NA> | [] | <NA> | <NA> | <NA> |
The objective
property contains the value of the objective function, and the feasible
property contains whether the constraints are satisfied.
print(f"{solution.objective=}, {solution.feasible=}")
solution.objective=1.0, solution.feasible=True
Since \(xy = 0\) when \(x = 1, y = 0\), all constraints are satisfied, so feasible
is True
. The value of the objective function is \(x + y = 1\).
What happens in the case of an infeasible solution, \(x = 1, y = 1\)?
solution11 = instance.evaluate({1: 1, 2: 1}) # x=1, y=1
print(f"{solution11.objective=}, {solution11.feasible=}")
solution11.objective=2.0, solution11.feasible=False
feasible = False
indicates that it is an infeasible solution.