* CMake has not been updated yet * bazel was compiling at least last week bazel: disable math opt facility_location.py missing some dependencies...
72 lines
2.4 KiB
Python
72 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
# Copyright 2010-2025 Google LLC
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
"""Solves an optimization problem with multiple objectives."""
|
|
|
|
from collections.abc import Sequence
|
|
|
|
from absl import app
|
|
from absl import flags
|
|
|
|
from ortools.math_opt.python import mathopt
|
|
|
|
_ENABLE_OUTPUT = flags.DEFINE_bool(
|
|
"enable_output", False, "should the solver logs be turned on"
|
|
)
|
|
|
|
|
|
def main(argv: Sequence[str]) -> None:
|
|
if len(argv) > 1:
|
|
raise app.UsageError("Too many command-line arguments.")
|
|
model = mathopt.Model()
|
|
# The model is:
|
|
# max x + y + 2 z
|
|
# s.t. x + y + z <= 1.5
|
|
# x, y in [0, 1]
|
|
# z binary
|
|
# With secondary objective
|
|
# max y
|
|
#
|
|
# The first problem is solved by any convex combination of:
|
|
# (0.5, 0, 1) and (0, 0.5, 1)
|
|
# But with the secondary objective, the unique solution is (0, 0.5, 1), with
|
|
# a primary objective value of 2.5 and secondary objective value of 0.5.
|
|
x = model.add_variable(lb=0, ub=1)
|
|
y = model.add_variable(lb=0, ub=1)
|
|
z = model.add_binary_variable()
|
|
model.add_linear_constraint(x + y + z <= 1.5)
|
|
model.maximize(x + y + 2 * z)
|
|
aux = model.add_maximization_objective(y, priority=1)
|
|
|
|
result = mathopt.solve(
|
|
model,
|
|
mathopt.SolverType.GUROBI,
|
|
params=mathopt.SolveParameters(enable_output=_ENABLE_OUTPUT.value),
|
|
)
|
|
if result.termination.reason != mathopt.TerminationReason.OPTIMAL:
|
|
raise ValueError(
|
|
f"Expected an optimal termination, found: {result.termination}"
|
|
)
|
|
print(f"primary objective: {result.objective_value()}")
|
|
print(f"x: {result.variable_values(x)}")
|
|
print(f"y: {result.variable_values(y)}")
|
|
print(f"z: {result.variable_values(z)}")
|
|
prim_sol = result.solutions[0].primal_solution
|
|
assert prim_sol is not None
|
|
print(f"secondary objective: {prim_sol.auxiliary_objective_values[aux]}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app.run(main)
|