math_opt: export from google3

* CMake has not been updated yet
* bazel was compiling at least last week

bazel: disable math opt facility_location.py

missing some dependencies...
This commit is contained in:
Corentin Le Molgat
2022-12-16 17:06:11 +01:00
parent 178084b3f7
commit 5bf70b691f
245 changed files with 28953 additions and 5680 deletions

View File

@@ -13,12 +13,16 @@
"""Model specific solver configuration (e.g. starting basis)."""
import dataclasses
from typing import Dict, List, Optional
import datetime
from typing import Dict, List, Optional, Set
from ortools.math_opt import model_parameters_pb2
from ortools.math_opt.python import linear_constraints
from ortools.math_opt.python import model
from ortools.math_opt.python import objectives
from ortools.math_opt.python import solution
from ortools.math_opt.python import sparse_containers
from ortools.math_opt.python import variables
@dataclasses.dataclass
@@ -51,10 +55,10 @@ class SolutionHint:
constraints to finite (and not NaN) double values.
"""
variable_values: Dict[model.Variable, float] = dataclasses.field(
variable_values: Dict[variables.Variable, float] = dataclasses.field(
default_factory=dict
)
dual_values: Dict[model.LinearConstraint, float] = dataclasses.field(
dual_values: Dict[linear_constraints.LinearConstraint, float] = dataclasses.field(
default_factory=dict
)
@@ -98,6 +102,81 @@ def parse_solution_hint(
)
@dataclasses.dataclass
class ObjectiveParameters:
"""Parameters for an individual objective in a multi-objective model.
This class mirrors (and can generate) the related proto
model_parameters_pb2.ObjectiveParametersProto.
Attributes:
objective_degradation_absolute_tolerance: Optional objective degradation
absolute tolerance. For a hierarchical multi-objective solver, each
objective fⁱ is processed in priority order: the solver determines the
optimal objective value Γⁱ, if it exists, subject to all constraints in
the model and the additional constraints that fᵏ(x) = Γᵏ (within
tolerances) for each k < i. If set, a solution is considered to be "within
tolerances" for this objective fᵏ if |fᵏ(x) - Γᵏ| ≤
`objective_degradation_absolute_tolerance`. See also
`objective_degradation_relative_tolerance`; if both parameters are set for
a given objective, the solver need only satisfy one to be considered
"within tolerances". If not None, must be nonnegative.
objective_degradation_relative_tolerance: Optional objective degradation
relative tolerance. For a hierarchical multi-objective solver, each
objective fⁱ is processed in priority order: the solver determines the
optimal objective value Γⁱ, if it exists, subject to all constraints in
the model and the additional constraints that fᵏ(x) = Γᵏ (within
tolerances) for each k < i. If set, a solution is considered to be "within
tolerances" for this objective fᵏ if |fᵏ(x) - Γᵏ| ≤
`objective_degradation_relative_tolerance` * |Γᵏ|. See also
`objective_degradation_absolute_tolerance`; if both parameters are set for
a given objective, the solver need only satisfy one to be considered
"within tolerances". If not None, must be nonnegative.
time_limit: The maximum time a solver should spend on optimizing this
particular objective (or infinite if not set). Note that this does not
supersede the global time limit in SolveParameters.time_limit; both will
be enforced when set. This value is not a hard limit, solve time may
slightly exceed this value.
"""
objective_degradation_absolute_tolerance: Optional[float] = None
objective_degradation_relative_tolerance: Optional[float] = None
time_limit: Optional[datetime.timedelta] = None
def to_proto(self) -> model_parameters_pb2.ObjectiveParametersProto:
"""Returns an equivalent protocol buffer."""
result = model_parameters_pb2.ObjectiveParametersProto()
if self.objective_degradation_absolute_tolerance is not None:
result.objective_degradation_absolute_tolerance = (
self.objective_degradation_absolute_tolerance
)
if self.objective_degradation_relative_tolerance is not None:
result.objective_degradation_relative_tolerance = (
self.objective_degradation_relative_tolerance
)
if self.time_limit is not None:
result.time_limit.FromTimedelta(self.time_limit)
return result
def parse_objective_parameters(
proto: model_parameters_pb2.ObjectiveParametersProto,
) -> ObjectiveParameters:
"""Returns an equivalent ObjectiveParameters to the input proto."""
result = ObjectiveParameters()
if proto.HasField("objective_degradation_absolute_tolerance"):
result.objective_degradation_absolute_tolerance = (
proto.objective_degradation_absolute_tolerance
)
if proto.HasField("objective_degradation_relative_tolerance"):
result.objective_degradation_relative_tolerance = (
proto.objective_degradation_relative_tolerance
)
if proto.HasField("time_limit"):
result.time_limit = proto.time_limit.ToTimedelta()
return result
@dataclasses.dataclass
class ModelSolveParameters:
"""Model specific solver configuration, for example, an initial basis.
@@ -109,8 +188,10 @@ class ModelSolveParameters:
variable_values_filter: Only return solution and primal ray values for
variables accepted by this filter (default accepts all variables).
dual_values_filter: Only return dual variable values and dual ray values for
linear constraints accepted by thei filter (default accepts all linear
linear constraints accepted by this filter (default accepts all linear
constraints).
quadratic_dual_values_filter: Only return quadratic constraint dual values
accepted by this filter (default accepts all quadratic constraints).
reduced_costs_filter: Only return reduced cost and dual ray values for
variables accepted by this filter (default accepts all variables).
initial_basis: If set, provides a warm start for simplex based solvers.
@@ -119,6 +200,14 @@ class ModelSolveParameters:
branching_priorities: Optional branching priorities. Variables with higher
values will be branched on first. Variables for which priorities are not
set get the solver's default priority (usually zero).
objective_parameters: Optional per objective parameters used only only for
multi-objective models.
lazy_linear_constraints: Optional lazy constraint annotations. Included
linear constraints will be marked as "lazy" with supporting solvers,
meaning that they will only be added to the working model as-needed as the
solver runs. Note that this an algorithmic hint that does not affect the
model's feasible region; solvers not supporting these annotations will
simply ignore it.
"""
variable_values_filter: sparse_containers.VariableFilter = (
@@ -127,14 +216,23 @@ class ModelSolveParameters:
dual_values_filter: sparse_containers.LinearConstraintFilter = (
sparse_containers.LinearConstraintFilter()
)
quadratic_dual_values_filter: sparse_containers.QuadraticConstraintFilter = (
sparse_containers.QuadraticConstraintFilter()
)
reduced_costs_filter: sparse_containers.VariableFilter = (
sparse_containers.VariableFilter()
)
initial_basis: Optional[solution.Basis] = None
solution_hints: List[SolutionHint] = dataclasses.field(default_factory=list)
branching_priorities: Dict[model.Variable, int] = dataclasses.field(
branching_priorities: Dict[variables.Variable, int] = dataclasses.field(
default_factory=dict
)
objective_parameters: Dict[objectives.Objective, ObjectiveParameters] = (
dataclasses.field(default_factory=dict)
)
lazy_linear_constraints: Set[linear_constraints.LinearConstraint] = (
dataclasses.field(default_factory=set)
)
def to_proto(self) -> model_parameters_pb2.ModelSolveParametersProto:
"""Returns an equivalent protocol buffer."""
@@ -143,6 +241,7 @@ class ModelSolveParameters:
result = model_parameters_pb2.ModelSolveParametersProto(
variable_values_filter=self.variable_values_filter.to_proto(),
dual_values_filter=self.dual_values_filter.to_proto(),
quadratic_dual_values_filter=self.quadratic_dual_values_filter.to_proto(),
reduced_costs_filter=self.reduced_costs_filter.to_proto(),
branching_priorities=sparse_containers.to_sparse_int32_vector_proto(
self.branching_priorities
@@ -152,4 +251,14 @@ class ModelSolveParameters:
result.initial_basis.CopyFrom(self.initial_basis.to_proto())
for hint in self.solution_hints:
result.solution_hints.append(hint.to_proto())
for obj, params in self.objective_parameters.items():
if isinstance(obj, objectives.AuxiliaryObjective):
result.auxiliary_objective_parameters[obj.id].CopyFrom(
params.to_proto()
)
else:
result.primary_objective_parameters.CopyFrom(params.to_proto())
result.lazy_linear_constraint_ids[:] = sorted(
con.id for con in self.lazy_linear_constraints
)
return result