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
6// http://www.apache.org/licenses/LICENSE-2.0
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.
16package operations_research.bop;
18option java_package = "com.google.ortools.bop";
19option java_multiple_files = true;
20option csharp_namespace = "Google.OrTools.Bop";
21// Method used to optimize a solution in Bop.
24message BopOptimizerMethod {
27 SAT_LINEAR_SEARCH = 15;
28 LINEAR_RELAXATION = 1;
30 RANDOM_FIRST_SOLUTION = 3;
31 RANDOM_CONSTRAINT_LNS = 4;
32 RANDOM_VARIABLE_LNS = 5;
34 LP_FIRST_SOLUTION = 8;
35 OBJECTIVE_FIRST_SOLUTION = 9;
36 USER_GUIDED_FIRST_SOLUTION = 14;
37 RANDOM_CONSTRAINT_LNS_GUIDED_BY_LP = 11;
38 RANDOM_VARIABLE_LNS_GUIDED_BY_LP = 12;
40 RELATION_GRAPH_LNS = 16;
41 RELATION_GRAPH_LNS_GUIDED_BY_LP = 17;
43 optional OptimizerType type = 1;
46// Set of optimizer methods to be run by an instance of the portfolio optimizer.
47// Note that in the current implementation, all the methods specified in the
48// repeated field methods will run on the same solver / thread.
49message BopSolverOptimizerSet {
50 repeated BopOptimizerMethod methods = 1;
53// Contains the definitions for all the bop algorithm parameters and their
57message BopParameters {
58 // Maximum time allowed in seconds to solve a problem.
59 // The counter will starts as soon as Solve() is called.
60 optional double max_time_in_seconds = 1 [default = inf];
62 // Maximum time allowed in deterministic time to solve a problem.
63 // The deterministic time should be correlated with the real time used by the
64 // solver, the time unit being roughly the order of magnitude of a second.
65 // The counter will starts as soon as SetParameters() or SolveWithTimeLimit()
67 optional double max_deterministic_time = 27 [default = inf];
69 // The max deterministic time given to the LP solver each time it is called.
70 // If this is not enough to solve the LP at hand, it will simply be called
71 // again later (and the solve will resume from where it stopped).
72 optional double lp_max_deterministic_time = 37 [default = 1.0];
74 // Maximum number of consecutive optimizer calls without improving the
75 // current solution. If this number is reached, the search will be aborted.
76 // Note that this parameter only applies when an initial solution has been
77 // found or is provided. Also note that there is no limit to the number of
78 // calls, when the parameter is not set.
79 optional int32 max_number_of_consecutive_failing_optimizer_calls = 35;
81 // Limit used to stop the optimization as soon as the relative gap is smaller
82 // than the given value.
83 // The relative gap is defined as:
84 // abs(solution_cost - best_bound)
85 // / max(abs(solution_cost), abs(best_bound)).
86 optional double relative_gap_limit = 28 [default = 1e-4];
88 // Maximum number of cascading decisions the solver might use to repair the
89 // current solution in the LS.
90 optional int32 max_num_decisions_in_ls = 2 [default = 4];
92 // Abort the LS search tree as soon as strictly more than this number of
93 // constraints are broken. The default is a large value which basically
94 // disable this heuristic.
95 optional int32 max_num_broken_constraints_in_ls = 38 [default = 0x7FFFFFFF];
97 // Whether the solver should log the search progress to LOG(INFO).
98 optional bool log_search_progress = 14 [default = false];
100 // Compute estimated impact at each iteration when true; only once when false.
101 optional bool compute_estimated_impact = 3 [default = true];
103 // Avoid exploring both branches (b, a, ...) and (a, b, ...).
104 optional bool prune_search_tree = 4 [default = false];
106 // Sort constraints by increasing total number of terms instead of number of
107 // contributing terms.
108 optional bool sort_constraints_by_num_terms = 5 [default = false];
110 // Use the random Large Neighborhood Search instead of the exhaustive one.
111 optional bool use_random_lns = 6 [default = true];
113 // The seed used to initialize the random generator.
115 // TODO(user): Some of our client test fail depending on this value! we need
116 // to fix them and ideally randomize our behavior from on test to the next so
117 // that this doesn't happen in the future.
118 optional int32 random_seed = 7 [default = 8];
120 // Number of variables to relax in the exhaustive Large Neighborhood Search.
121 optional int32 num_relaxed_vars = 8 [default = 10];
123 // The number of conflicts the SAT solver has to solve a random LNS
125 optional int32 max_number_of_conflicts_in_random_lns = 9 [default = 2500];
127 // Number of tries in the random lns.
128 optional int32 num_random_lns_tries = 10 [default = 1];
130 // Maximum number of backtracks times the number of variables in Local Search,
131 // ie. max num backtracks == max_number_of_backtracks_in_ls / num variables.
132 optional int64 max_number_of_backtracks_in_ls = 11 [default = 100000000];
134 // Use Large Neighborhood Search based on the LP relaxation.
135 optional bool use_lp_lns = 12 [default = true];
137 // Whether we use sat propagation to choose the lns neighbourhood.
138 optional bool use_sat_to_choose_lns_neighbourhood = 15 [default = true];
140 // The number of conflicts the SAT solver has to solve a random LNS
141 // subproblem for the quick check of infeasibility.
142 optional int32 max_number_of_conflicts_for_quick_check = 16 [default = 10];
144 // If true, find and exploit the eventual symmetries of the problem.
146 // TODO(user): turn this on by default once the symmetry finder becomes fast
147 // enough to be negligeable for most problem. Or at least support a time
149 optional bool use_symmetry = 17 [default = false];
151 // If true, find and exploit symmetries in proving satisfiability in the first
153 // This feature is experimental. On some problems, computing symmetries may
154 // run forever. You may also run into unforseen problems as this feature was
155 // not extensively tested.
156 optional bool exploit_symmetry_in_sat_first_solution = 40 [default = false];
158 // The number of conflicts the SAT solver has to generate a random solution.
159 optional int32 max_number_of_conflicts_in_random_solution_generation = 20
162 // The maximum number of assignments the Local Search iterates on during one
163 // try. Note that if the Local Search is called again on the same solution
164 // it will not restart from scratch but will iterate on the next
165 // max_number_of_explored_assignments_per_try_in_ls assignments.
166 optional int64 max_number_of_explored_assignments_per_try_in_ls = 21
169 // Whether we use an hash set during the LS to avoid exploring more than once
170 // the "same" state. Note that because the underlying SAT solver may learn
171 // information in the middle of the LS, this may make the LS slightly less
172 // "complete", but it should be faster.
173 optional bool use_transposition_table_in_ls = 22 [default = true];
175 // Whether we keep a list of variable that can potentially repair in one flip
176 // all the current infeasible constraints (such variable must at least appear
177 // in all the infeasible constraints for this to happen).
178 optional bool use_potential_one_flip_repairs_in_ls = 39 [default = false];
180 // Whether we use the learned binary clauses in the Linear Relaxation.
181 optional bool use_learned_binary_clauses_in_lp = 23 [default = true];
183 // The number of solvers used to run Bop. Note that one thread will be created
184 // per solver. The type of communication between solvers is specified by the
185 // synchronization_type parameter.
186 optional int32 number_of_solvers = 24 [default = 1];
188 // Defines how the different solvers are synchronized during the search.
189 // Note that the synchronization (if any) occurs before each call to an
190 // optimizer (the smallest granularity of the solver in a parallel context).
191 enum ThreadSynchronizationType {
192 // No synchronization. The solvers run independently until the time limit
193 // is reached; Then learned information from each solver are aggregated.
194 // The final solution is the best of all found solutions.
195 // Pros: - No need to wait for another solver to complete its task,
196 // - Adding a new solver always improves the final solution (In the
197 // current implementation it still depends on the machine load and
199 // Cons: - No learning between solvers.
200 NO_SYNCHRONIZATION = 0;
202 // Synchronize all solvers. Each solver waits for all other solvers to
203 // complete the previous optimizer run, before running again.
204 // The final solution is the best of all found solutions.
205 // Pros: - Full learning between solvers.
206 // Cons: - A lot of waiting time when solvers don't run at the exact same
208 // - The quality of the final solution depends on the number of
209 // solvers, adding one more solver might lead to poorer results
210 // because the search goes on a different path.
213 // Solver i synchronizes with solvers 0..i-1.
214 // This is a good tradeoff between NO_SYNCHRONIZATION and SYNCHRONIZE_ALL:
215 // communication while keeping a relative determinism on the result even
216 // when the number of solvers increases.
217 // The final solution is the best of all found solutions.
218 // Pros: - Solver i learns from i different solvers,
219 // - Adding a new solver always improves the final solution (In the
220 // current implementation it still depends on the machine load and
222 // Cons: - No full learning,
223 // - Some solvers need to wait for synchronization.
224 SYNCHRONIZE_ON_RIGHT = 2;
226 optional ThreadSynchronizationType synchronization_type = 25
227 [default = NO_SYNCHRONIZATION];
229 // List of set of optimizers to be run by the solvers.
230 // Note that the i_th solver will run the
231 // min(i, solver_optimizer_sets_size())_th optimizer set.
232 // The default is defined by default_solver_optimizer_sets (only one set).
233 repeated BopSolverOptimizerSet solver_optimizer_sets = 26;
234 optional string default_solver_optimizer_sets = 33
235 [default = "methods:{type:LOCAL_SEARCH } "
236 "methods:{type:RANDOM_FIRST_SOLUTION } "
237 "methods:{type:LINEAR_RELAXATION } "
238 "methods:{type:LP_FIRST_SOLUTION } "
239 "methods:{type:OBJECTIVE_FIRST_SOLUTION } "
240 "methods:{type:USER_GUIDED_FIRST_SOLUTION } "
241 "methods:{type:RANDOM_CONSTRAINT_LNS_GUIDED_BY_LP } "
242 "methods:{type:RANDOM_VARIABLE_LNS_GUIDED_BY_LP } "
243 "methods:{type:RELATION_GRAPH_LNS } "
244 "methods:{type:RELATION_GRAPH_LNS_GUIDED_BY_LP } "
245 "methods:{type:RANDOM_CONSTRAINT_LNS } "
246 "methods:{type:RANDOM_VARIABLE_LNS } "
247 "methods:{type:SAT_CORE_BASED } "
248 "methods:{type:COMPLETE_LNS } "];
250 // Use strong branching in the linear relaxation optimizer.
251 // The strong branching is a what-if analysis on each variable v, i.e.
252 // compute the best bound when v is assigned to true, compute the best bound
253 // when v is assigned to false, and then use those best bounds to improve the
254 // overall best bound.
255 // This is useful to improve the best_bound, but also to fix some variables
257 // Note that using probing might be time consuming as it runs the LP solver
258 // 2 * num_variables times.
259 optional bool use_lp_strong_branching = 29 [default = false];
261 // Only try to decompose the problem when the number of variables is greater
262 // than the threshold.
263 optional int32 decomposer_num_variables_threshold = 30 [default = 50];
265 // The number of BopSolver created (thread pool workers) used by the integral
266 // solver to solve a decomposed problem.
267 // TODO(user): Merge this with the number_of_solvers parameter.
268 optional int32 num_bop_solvers_used_by_decomposition = 31 [default = 1];
270 // HACK. To avoid spending too little time on small problems, spend at least
271 // this time solving each of the decomposed sub-problem. This only make sense
272 // if num_bop_solvers_used_by_decomposition is greater than 1 so that the
273 // overhead can be "absorbed" by the other threads.
274 optional double decomposed_problem_min_time_in_seconds = 36 [default = 0.0];
276 // The first solutions based on guided SAT will work in chunk of that many
277 // conflicts at the time. This allows to simulate parallelism between the
278 // different guiding strategy on a single core.
279 optional int32 guided_sat_conflicts_chunk = 34 [default = 1000];
281 // The maximum number of time the LP solver will run to feasibility for pure
282 // feasibility problems (with a constant-valued objective function). Set this
283 // to a small value, e.g., 1, if fractional solutions offer useful guidance to
284 // other solvers in the portfolio. A negative value means no limit.
285 optional int32 max_lp_solve_for_feasibility_problems = 41 [default = 0];