ortools.math_opt.python.model_parameters
Model specific solver configuration (e.g. starting basis).
1# Copyright 2010-2024 Google LLC 2# Licensed under the Apache License, Version 2.0 (the "License"); 3# you may not use this file except in compliance with the License. 4# You may obtain a copy of the License at 5# 6# http://www.apache.org/licenses/LICENSE-2.0 7# 8# Unless required by applicable law or agreed to in writing, software 9# distributed under the License is distributed on an "AS IS" BASIS, 10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11# See the License for the specific language governing permissions and 12# limitations under the License. 13 14"""Model specific solver configuration (e.g. starting basis).""" 15import dataclasses 16from typing import Dict, List, Optional 17 18from ortools.math_opt import model_parameters_pb2 19from ortools.math_opt.python import model 20from ortools.math_opt.python import solution 21from ortools.math_opt.python import sparse_containers 22 23 24@dataclasses.dataclass 25class SolutionHint: 26 """A suggested starting solution for the solver. 27 28 MIP solvers generally only want primal information (`variable_values`), 29 while LP solvers want both primal and dual information (`dual_values`). 30 31 Many MIP solvers can work with: (1) partial solutions that do not specify all 32 variables or (2) infeasible solutions. In these cases, solvers typically solve 33 a sub-MIP to complete/correct the hint. 34 35 How the hint is used by the solver, if at all, is highly dependent on the 36 solver, the problem type, and the algorithm used. The most reliable way to 37 ensure your hint has an effect is to read the underlying solvers logs with 38 and without the hint. 39 40 Simplex-based LP solvers typically prefer an initial basis to a solution 41 hint (they need to crossover to convert the hint to a basic feasible 42 solution otherwise). 43 44 Floating point values should be finite and not NaN, they are validated by 45 MathOpt at Solve() time (resulting in an exception). 46 47 Attributes: 48 variable_values: a potentially partial assignment from the model's primal 49 variables to finite (and not NaN) double values. 50 dual_values: a potentially partial assignment from the model's linear 51 constraints to finite (and not NaN) double values. 52 """ 53 54 variable_values: Dict[model.Variable, float] = dataclasses.field( 55 default_factory=dict 56 ) 57 dual_values: Dict[model.LinearConstraint, float] = dataclasses.field( 58 default_factory=dict 59 ) 60 61 def to_proto(self) -> model_parameters_pb2.SolutionHintProto: 62 """Returns an equivalent protocol buffer to this.""" 63 return model_parameters_pb2.SolutionHintProto( 64 variable_values=sparse_containers.to_sparse_double_vector_proto( 65 self.variable_values 66 ), 67 dual_values=sparse_containers.to_sparse_double_vector_proto( 68 self.dual_values 69 ), 70 ) 71 72 73def parse_solution_hint( 74 hint_proto: model_parameters_pb2.SolutionHintProto, mod: model.Model 75) -> SolutionHint: 76 """Returns an equivalent SolutionHint to `hint_proto`. 77 78 Args: 79 hint_proto: The solution, as encoded by the ids of the variables and 80 constraints. 81 mod: A MathOpt Model that must contain variables and linear constraints with 82 the ids from hint_proto. 83 84 Returns: 85 A SolutionHint equivalent. 86 87 Raises: 88 ValueError if hint_proto is invalid or refers to variables or constraints 89 not in mod. 90 """ 91 return SolutionHint( 92 variable_values=sparse_containers.parse_variable_map( 93 hint_proto.variable_values, mod 94 ), 95 dual_values=sparse_containers.parse_linear_constraint_map( 96 hint_proto.dual_values, mod 97 ), 98 ) 99 100 101@dataclasses.dataclass 102class ModelSolveParameters: 103 """Model specific solver configuration, for example, an initial basis. 104 105 This class mirrors (and can generate) the related proto 106 model_parameters_pb2.ModelSolveParametersProto. 107 108 Attributes: 109 variable_values_filter: Only return solution and primal ray values for 110 variables accepted by this filter (default accepts all variables). 111 dual_values_filter: Only return dual variable values and dual ray values for 112 linear constraints accepted by thei filter (default accepts all linear 113 constraints). 114 reduced_costs_filter: Only return reduced cost and dual ray values for 115 variables accepted by this filter (default accepts all variables). 116 initial_basis: If set, provides a warm start for simplex based solvers. 117 solution_hints: Optional solution hints. If the underlying solver only 118 accepts a single hint, the first hint is used. 119 branching_priorities: Optional branching priorities. Variables with higher 120 values will be branched on first. Variables for which priorities are not 121 set get the solver's default priority (usually zero). 122 """ 123 124 variable_values_filter: sparse_containers.VariableFilter = ( 125 sparse_containers.VariableFilter() 126 ) 127 dual_values_filter: sparse_containers.LinearConstraintFilter = ( 128 sparse_containers.LinearConstraintFilter() 129 ) 130 reduced_costs_filter: sparse_containers.VariableFilter = ( 131 sparse_containers.VariableFilter() 132 ) 133 initial_basis: Optional[solution.Basis] = None 134 solution_hints: List[SolutionHint] = dataclasses.field(default_factory=list) 135 branching_priorities: Dict[model.Variable, int] = dataclasses.field( 136 default_factory=dict 137 ) 138 139 def to_proto(self) -> model_parameters_pb2.ModelSolveParametersProto: 140 """Returns an equivalent protocol buffer.""" 141 # TODO(b/236289022): these methods should check that the variables are from 142 # the correct model. 143 result = model_parameters_pb2.ModelSolveParametersProto( 144 variable_values_filter=self.variable_values_filter.to_proto(), 145 dual_values_filter=self.dual_values_filter.to_proto(), 146 reduced_costs_filter=self.reduced_costs_filter.to_proto(), 147 branching_priorities=sparse_containers.to_sparse_int32_vector_proto( 148 self.branching_priorities 149 ), 150 ) 151 if self.initial_basis: 152 result.initial_basis.CopyFrom(self.initial_basis.to_proto()) 153 for hint in self.solution_hints: 154 result.solution_hints.append(hint.to_proto()) 155 return result
25@dataclasses.dataclass 26class SolutionHint: 27 """A suggested starting solution for the solver. 28 29 MIP solvers generally only want primal information (`variable_values`), 30 while LP solvers want both primal and dual information (`dual_values`). 31 32 Many MIP solvers can work with: (1) partial solutions that do not specify all 33 variables or (2) infeasible solutions. In these cases, solvers typically solve 34 a sub-MIP to complete/correct the hint. 35 36 How the hint is used by the solver, if at all, is highly dependent on the 37 solver, the problem type, and the algorithm used. The most reliable way to 38 ensure your hint has an effect is to read the underlying solvers logs with 39 and without the hint. 40 41 Simplex-based LP solvers typically prefer an initial basis to a solution 42 hint (they need to crossover to convert the hint to a basic feasible 43 solution otherwise). 44 45 Floating point values should be finite and not NaN, they are validated by 46 MathOpt at Solve() time (resulting in an exception). 47 48 Attributes: 49 variable_values: a potentially partial assignment from the model's primal 50 variables to finite (and not NaN) double values. 51 dual_values: a potentially partial assignment from the model's linear 52 constraints to finite (and not NaN) double values. 53 """ 54 55 variable_values: Dict[model.Variable, float] = dataclasses.field( 56 default_factory=dict 57 ) 58 dual_values: Dict[model.LinearConstraint, float] = dataclasses.field( 59 default_factory=dict 60 ) 61 62 def to_proto(self) -> model_parameters_pb2.SolutionHintProto: 63 """Returns an equivalent protocol buffer to this.""" 64 return model_parameters_pb2.SolutionHintProto( 65 variable_values=sparse_containers.to_sparse_double_vector_proto( 66 self.variable_values 67 ), 68 dual_values=sparse_containers.to_sparse_double_vector_proto( 69 self.dual_values 70 ), 71 )
A suggested starting solution for the solver.
MIP solvers generally only want primal information (variable_values
),
while LP solvers want both primal and dual information (dual_values
).
Many MIP solvers can work with: (1) partial solutions that do not specify all variables or (2) infeasible solutions. In these cases, solvers typically solve a sub-MIP to complete/correct the hint.
How the hint is used by the solver, if at all, is highly dependent on the solver, the problem type, and the algorithm used. The most reliable way to ensure your hint has an effect is to read the underlying solvers logs with and without the hint.
Simplex-based LP solvers typically prefer an initial basis to a solution hint (they need to crossover to convert the hint to a basic feasible solution otherwise).
Floating point values should be finite and not NaN, they are validated by MathOpt at Solve() time (resulting in an exception).
Attributes:
- variable_values: a potentially partial assignment from the model's primal variables to finite (and not NaN) double values.
- dual_values: a potentially partial assignment from the model's linear constraints to finite (and not NaN) double values.
62 def to_proto(self) -> model_parameters_pb2.SolutionHintProto: 63 """Returns an equivalent protocol buffer to this.""" 64 return model_parameters_pb2.SolutionHintProto( 65 variable_values=sparse_containers.to_sparse_double_vector_proto( 66 self.variable_values 67 ), 68 dual_values=sparse_containers.to_sparse_double_vector_proto( 69 self.dual_values 70 ), 71 )
Returns an equivalent protocol buffer to this.
74def parse_solution_hint( 75 hint_proto: model_parameters_pb2.SolutionHintProto, mod: model.Model 76) -> SolutionHint: 77 """Returns an equivalent SolutionHint to `hint_proto`. 78 79 Args: 80 hint_proto: The solution, as encoded by the ids of the variables and 81 constraints. 82 mod: A MathOpt Model that must contain variables and linear constraints with 83 the ids from hint_proto. 84 85 Returns: 86 A SolutionHint equivalent. 87 88 Raises: 89 ValueError if hint_proto is invalid or refers to variables or constraints 90 not in mod. 91 """ 92 return SolutionHint( 93 variable_values=sparse_containers.parse_variable_map( 94 hint_proto.variable_values, mod 95 ), 96 dual_values=sparse_containers.parse_linear_constraint_map( 97 hint_proto.dual_values, mod 98 ), 99 )
Returns an equivalent SolutionHint to hint_proto
.
Arguments:
- hint_proto: The solution, as encoded by the ids of the variables and constraints.
- mod: A MathOpt Model that must contain variables and linear constraints with the ids from hint_proto.
Returns:
A SolutionHint equivalent.
Raises:
- ValueError if hint_proto is invalid or refers to variables or constraints
- not in mod.
102@dataclasses.dataclass 103class ModelSolveParameters: 104 """Model specific solver configuration, for example, an initial basis. 105 106 This class mirrors (and can generate) the related proto 107 model_parameters_pb2.ModelSolveParametersProto. 108 109 Attributes: 110 variable_values_filter: Only return solution and primal ray values for 111 variables accepted by this filter (default accepts all variables). 112 dual_values_filter: Only return dual variable values and dual ray values for 113 linear constraints accepted by thei filter (default accepts all linear 114 constraints). 115 reduced_costs_filter: Only return reduced cost and dual ray values for 116 variables accepted by this filter (default accepts all variables). 117 initial_basis: If set, provides a warm start for simplex based solvers. 118 solution_hints: Optional solution hints. If the underlying solver only 119 accepts a single hint, the first hint is used. 120 branching_priorities: Optional branching priorities. Variables with higher 121 values will be branched on first. Variables for which priorities are not 122 set get the solver's default priority (usually zero). 123 """ 124 125 variable_values_filter: sparse_containers.VariableFilter = ( 126 sparse_containers.VariableFilter() 127 ) 128 dual_values_filter: sparse_containers.LinearConstraintFilter = ( 129 sparse_containers.LinearConstraintFilter() 130 ) 131 reduced_costs_filter: sparse_containers.VariableFilter = ( 132 sparse_containers.VariableFilter() 133 ) 134 initial_basis: Optional[solution.Basis] = None 135 solution_hints: List[SolutionHint] = dataclasses.field(default_factory=list) 136 branching_priorities: Dict[model.Variable, int] = dataclasses.field( 137 default_factory=dict 138 ) 139 140 def to_proto(self) -> model_parameters_pb2.ModelSolveParametersProto: 141 """Returns an equivalent protocol buffer.""" 142 # TODO(b/236289022): these methods should check that the variables are from 143 # the correct model. 144 result = model_parameters_pb2.ModelSolveParametersProto( 145 variable_values_filter=self.variable_values_filter.to_proto(), 146 dual_values_filter=self.dual_values_filter.to_proto(), 147 reduced_costs_filter=self.reduced_costs_filter.to_proto(), 148 branching_priorities=sparse_containers.to_sparse_int32_vector_proto( 149 self.branching_priorities 150 ), 151 ) 152 if self.initial_basis: 153 result.initial_basis.CopyFrom(self.initial_basis.to_proto()) 154 for hint in self.solution_hints: 155 result.solution_hints.append(hint.to_proto()) 156 return result
Model specific solver configuration, for example, an initial basis.
This class mirrors (and can generate) the related proto model_parameters_pb2.ModelSolveParametersProto.
Attributes:
- 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 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.
- solution_hints: Optional solution hints. If the underlying solver only accepts a single hint, the first hint is used.
- 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).
140 def to_proto(self) -> model_parameters_pb2.ModelSolveParametersProto: 141 """Returns an equivalent protocol buffer.""" 142 # TODO(b/236289022): these methods should check that the variables are from 143 # the correct model. 144 result = model_parameters_pb2.ModelSolveParametersProto( 145 variable_values_filter=self.variable_values_filter.to_proto(), 146 dual_values_filter=self.dual_values_filter.to_proto(), 147 reduced_costs_filter=self.reduced_costs_filter.to_proto(), 148 branching_priorities=sparse_containers.to_sparse_int32_vector_proto( 149 self.branching_priorities 150 ), 151 ) 152 if self.initial_basis: 153 result.initial_basis.CopyFrom(self.initial_basis.to_proto()) 154 for hint in self.solution_hints: 155 result.solution_hints.append(hint.to_proto()) 156 return result
Returns an equivalent protocol buffer.