OR-Tools  9.2
bop_portfolio.h
Go to the documentation of this file.
1// Copyright 2010-2021 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#ifndef OR_TOOLS_BOP_BOP_PORTFOLIO_H_
15#define OR_TOOLS_BOP_BOP_PORTFOLIO_H_
16
17#include <cstdint>
18
21#include "ortools/bop/bop_lns.h"
29#include "ortools/util/stats.h"
31
32namespace operations_research {
33namespace bop {
34
35DEFINE_INT_TYPE(OptimizerIndex, int);
36const OptimizerIndex kInvalidOptimizerIndex(-1);
37
38// Forward declaration.
40
41// This class implements a portfolio optimizer.
42// The portfolio currently includes all the following optimizers:
43// - SAT_CORE_BASED
44// - SAT_LINEAR_SEARCH
45// - LINEAR_RELAXATION
46// - LOCAL_SEARCH
47// - RANDOM_FIRST_SOLUTION
48// - RANDOM_CONSTRAINT_LNS
49// - RANDOM_VARIABLE_LNS
50// - COMPLETE_LNS
51// - LP_FIRST_SOLUTION
52// - OBJECTIVE_FIRST_SOLUTION
53// - USER_GUIDED_FIRST_SOLUTION
54// - FEASIBILITY_PUMP_FIRST_SOLUTION
55// - RANDOM_CONSTRAINT_LNS_GUIDED_BY_LP
56// - RANDOM_VARIABLE_LNS_GUIDED_BY_LP
57// - RELATION_GRAPH_LNS
58// - RELATION_GRAPH_LNS_GUIDED_BY_LP
59//
60// At each call of Optimize(), the portfolio optimizer selects the next
61// optimizer to run and runs it. The selection is auto-adaptative, meaning that
62// optimizers that succeeded more in the previous calls to Optimizer() are more
63// likely to be selected.
65 public:
66 PortfolioOptimizer(const ProblemState& problem_state,
68 const BopSolverOptimizerSet& optimizer_set,
69 const std::string& name);
70 ~PortfolioOptimizer() override;
71
72 bool ShouldBeRun(const ProblemState& problem_state) const override {
73 return true;
74 }
76 const ProblemState& problem_state, LearnedInfo* learned_info,
77 TimeLimit* time_limit) override;
78
79 private:
80 BopOptimizerBase::Status SynchronizeIfNeeded(
81 const ProblemState& problem_state);
82 void AddOptimizer(const sat::LinearBooleanProblem& problem,
84 const BopOptimizerMethod& optimizer_method);
85 void CreateOptimizers(const sat::LinearBooleanProblem& problem,
87 const BopSolverOptimizerSet& optimizer_set);
88
89 random_engine_t random_;
90 int64_t state_update_stamp_;
91 BopConstraintTerms objective_terms_;
92 std::unique_ptr<OptimizerSelector> selector_;
94 sat::SatSolver sat_propagator_;
95 BopParameters parameters_;
96 double lower_bound_;
97 double upper_bound_;
98 int number_of_consecutive_failing_optimizers_;
99};
100
101// This class is providing an adaptative selector for optimizers based on
102// their past successes and deterministic time spent.
104 public:
105 // Note that the list of optimizers is only used to get the names for
106 // debug purposes, the ownership of the optimizers is not transferred.
107 explicit OptimizerSelector(
109
110 // Selects the next optimizer to run based on the user defined order and
111 // history of success. Returns kInvalidOptimizerIndex if no optimizer is
112 // selectable and runnable (see the functions below).
113 //
114 // The optimizer is selected using the following algorithm (L being the
115 // sorted list of optimizers, and l the position of the last selected
116 // optimizer):
117 // a- If a new solution has been found by optimizer l, select the first
118 // optimizer l' in L, l' >= 0, that can run.
119 // b- If optimizer l didn't find a new solution, select the first
120 // optimizer l', with l' > l, such that its deterministic time spent
121 // since last solution is smaller than the deterministic time spent
122 // by any runnable optimizer in 1..l since last solution.
123 // If no such optimizer is available, go to option a.
124 OptimizerIndex SelectOptimizer();
125
126 // Updates the internal metrics to decide which optimizer to select.
127 // This method should be called each time the selected optimizer is run.
128 //
129 // The gain corresponds to the reward to assign to the solver; It could for
130 // instance be the difference in cost between the last and the current
131 // solution.
132 //
133 // The time spent corresponds to the time the optimizer spent; To make the
134 // behavior deterministic, it is recommended to use the deterministic time
135 // instead of the elapsed time.
136 //
137 // The optimizers are sorted based on their score each time a new solution is
138 // found.
139 void UpdateScore(int64_t gain, double time_spent);
140
141 // Marks the given optimizer as not selectable until UpdateScore() is called
142 // with a positive gain. In which case, all optimizer will become selectable
143 // again.
144 void TemporarilyMarkOptimizerAsUnselectable(OptimizerIndex optimizer_index);
145
146 // Sets whether or not an optimizer is "runnable". Like a non-selectable one,
147 // a non-runnable optimizer will never be returned by SelectOptimizer().
148 //
149 // TODO(user): Maybe we should simply have the notion of selectability here
150 // and let the client handle the logic to decide what optimizer are selectable
151 // or not.
152 void SetOptimizerRunnability(OptimizerIndex optimizer_index, bool runnable);
153
154 // Returns statistics about the given optimizer.
155 std::string PrintStats(OptimizerIndex optimizer_index) const;
156 int NumCallsForOptimizer(OptimizerIndex optimizer_index) const;
157
158 // Prints some debug information. Should not be used in production.
159 void DebugPrint() const;
160
161 private:
162 // Updates internals when a solution has been found using the selected
163 // optimizer.
164 void NewSolutionFound(int64_t gain);
165
166 // Updates the deterministic time spent by the selected optimizer.
167 void UpdateDeterministicTime(double time_spent);
168
169 // Sorts optimizers based on their scores.
170 void UpdateOrder();
171
172 struct RunInfo {
173 RunInfo(OptimizerIndex i, const std::string& n)
174 : optimizer_index(i),
175 name(n),
176 num_successes(0),
177 num_calls(0),
178 total_gain(0),
179 time_spent(0.0),
180 time_spent_since_last_solution(0),
181 runnable(true),
182 selectable(true),
183 score(0.0) {}
184
185 bool RunnableAndSelectable() const { return runnable && selectable; }
186
187 OptimizerIndex optimizer_index;
188 std::string name;
189 int num_successes;
190 int num_calls;
191 int64_t total_gain;
192 double time_spent;
193 double time_spent_since_last_solution;
194 bool runnable;
195 bool selectable;
196 double score;
197 };
198
199 std::vector<RunInfo> run_infos_;
201 int selected_index_;
202};
203
204} // namespace bop
205} // namespace operations_research
206#endif // OR_TOOLS_BOP_BOP_PORTFOLIO_H_
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
Definition: time_limit.h:106
const std::string & name() const
Definition: bop_base.h:49
void UpdateScore(int64_t gain, double time_spent)
std::string PrintStats(OptimizerIndex optimizer_index) const
int NumCallsForOptimizer(OptimizerIndex optimizer_index) const
OptimizerSelector(const absl::StrongVector< OptimizerIndex, BopOptimizerBase * > &optimizers)
void TemporarilyMarkOptimizerAsUnselectable(OptimizerIndex optimizer_index)
void SetOptimizerRunnability(OptimizerIndex optimizer_index, bool runnable)
bool ShouldBeRun(const ProblemState &problem_state) const override
Definition: bop_portfolio.h:72
Status Optimize(const BopParameters &parameters, const ProblemState &problem_state, LearnedInfo *learned_info, TimeLimit *time_limit) override
PortfolioOptimizer(const ProblemState &problem_state, const BopParameters &parameters, const BopSolverOptimizerSet &optimizer_set, const std::string &name)
SatParameters parameters
ModelSharedTimeLimit * time_limit
const std::string name
const OptimizerIndex kInvalidOptimizerIndex(-1)
DEFINE_INT_TYPE(OptimizerIndex, int)
Collection of objects used to extend the Constraint Solver library.
std::mt19937 random_engine_t
Definition: random_engine.h:23