Google OR-Tools v9.9
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
max_hs.h
Go to the documentation of this file.
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#ifndef OR_TOOLS_SAT_MAX_HS_H_
15#define OR_TOOLS_SAT_MAX_HS_H_
16
17#include <stdint.h>
18
19#include <cstdint>
20#include <functional>
21#include <utility>
22#include <vector>
23
24#include "absl/container/flat_hash_map.h"
25#include "absl/types/span.h"
27#include "ortools/linear_solver/linear_solver.pb.h"
28#include "ortools/sat/cp_model.pb.h"
30#include "ortools/sat/integer.h"
34#include "ortools/sat/model.h"
36#include "ortools/sat/sat_parameters.pb.h"
39#include "ortools/sat/util.h"
41
42namespace operations_research {
43namespace sat {
44
45// Generalization of the max-HS algorithm (HS stands for Hitting Set). This is
46// similar to MinimizeWithCoreAndLazyEncoding() but it uses a hybrid approach
47// with a MIP solver to handle the discovered infeasibility cores.
48//
49// See, Jessica Davies and Fahiem Bacchus, "Solving MAXSAT by Solving a
50// Sequence of Simpler SAT Instances",
51// http://www.cs.toronto.edu/~jdavies/daviesCP11.pdf"
52//
53// Note that an implementation of this approach won the 2016 max-SAT competition
54// on the industrial category, see
55// http://maxsat.ia.udl.cat/results/#wpms-industrial
56//
57// TODO(user): This class requires linking with the SCIP MIP solver which is
58// quite big, maybe we should find a way not to do that.
60 public:
61 HittingSetOptimizer(const CpModelProto& model_proto,
62 const ObjectiveDefinition& objective_definition,
63 const std::function<void()>& feasible_solution_observer,
64 Model* model);
65
67
68 private:
69 const int kUnextracted = -1;
70
71 SatSolver::Status FindMultipleCoresForMaxHs(
72 std::vector<Literal> assumptions,
73 std::vector<std::vector<Literal>>* core);
74
75 // Extract the objective variables, which is the smallest possible useful set.
76 void ExtractObjectiveVariables();
77
78 // Calls ComputeAdditionalVariablesToExtract() and extract all new variables.
79 // This must be called after the linear relaxation has been filled.
80 void ExtractAdditionalVariables(absl::Span<const IntegerVariable> to_extract);
81
82 // Heuristic to decide which variables (in addition to the objective
83 // variables) to extract.
84 // We use a sorted map to have a deterministic model.
85 std::vector<IntegerVariable> ComputeAdditionalVariablesToExtract();
86
87 // Checks whethers a variable is extracted, and return the index in the MIP
88 // model. It returns the same indef for both the variable and its negation.
89 //
90 // Node that the domain of the MIP variable is equal to the domain of the
91 // positive variable.
92 int GetExtractedIndex(IntegerVariable var) const;
93
94 // Returns false if the model is unsat.
95 bool ComputeInitialMpModel();
96
97 // Project the at_most_one constraint on the set of extracted variables.
98 void ProjectAndAddAtMostOne(const std::vector<Literal>& literals);
99
100 // Project the linear constraint on the set of extracted variables. Non
101 // extracted variables are used to 'extend' the lower and upper bound of the
102 // linear equation.
103 //
104 // It returns a non-null proto if the constraints was successfully extracted.
105 MPConstraintProto* ProjectAndAddLinear(const LinearConstraint& linear);
106
107 // Auxiliary method used by ProjectAndAddLinear(), and TightenLinear().
108 void ProjectLinear(const LinearConstraint& linear, MPConstraintProto* ct);
109
110 // Imports variable bounds from the shared bound manager (in parallel),
111 // updates the domains of the SAT variables, lower and upper bounds of
112 // extracted variables. Then it scans the extracted linear constraints and
113 // recompute its lower and upper bounds.
114 void TightenMpModel();
115
116 // Processes the cores from the SAT solver and add them to the MPModel.
117 void AddCoresToTheMpModel(const std::vector<std::vector<Literal>>& cores);
118
119 // Builds the assumptions from the current MP solution.
120 std::vector<Literal> BuildAssumptions(
121 IntegerValue stratified_threshold,
122 IntegerValue* next_stratified_threshold);
123
124 // This will be called each time a feasible solution is found.
125 bool ProcessSolution();
126
127 // Import shared information. Returns false if the model is unsat.
128 bool ImportFromOtherWorkers();
129
130 // Problem definition
131 const CpModelProto& model_proto_;
132 const ObjectiveDefinition& objective_definition_;
133 const std::function<void()> feasible_solution_observer_;
134
135 // Model object.
136 Model* model_;
137 SatSolver* sat_solver_;
138 TimeLimit* time_limit_;
139 const SatParameters& parameters_;
140 ModelRandomGenerator* random_;
141 SharedResponseManager* shared_response_;
142 IntegerTrail* integer_trail_;
143 IntegerEncoder* integer_encoder_;
144
145 // Linear model.
146 MPConstraintProto* obj_constraint_ = nullptr;
147 MPModelRequest request_;
148 MPSolutionResponse response_;
149
150 // Linear relaxation of the SAT model.
151 LinearRelaxation relaxation_;
152
153 // TODO(user): The core is returned in the same order as the assumptions,
154 // so we don't really need this map, we could just do a linear scan to
155 // recover which node are part of the core.
156 absl::flat_hash_map<LiteralIndex, std::vector<int>> assumption_to_indices_;
157
158 // New Booleans variable in the MIP model to represent X OP cte (OP is => if
159 // the variable of the objective is positive, <= otherwise).
160 absl::flat_hash_map<std::pair<int, int64_t>, int> mp_integer_literals_;
161
162 // Extraction info used in the projection of the model onto the extracted
163 // variables.
164 // By convention, we always associate the MPVariableProto with both the
165 // positive and the negative SAT variable.
167
168 // The list of <positive sat var, mp var proto> created during the
169 // ExtractVariable() method.
170 std::vector<std::pair<IntegerVariable, MPVariableProto*>>
171 extracted_variables_info_;
172
173 int num_extracted_at_most_ones_ = 0;
174 std::vector<std::pair<int, MPConstraintProto*>> linear_extract_info_;
175
176 // Normalized objective definition. All coefficients are positive.
177 std::vector<IntegerVariable> normalized_objective_variables_;
178 std::vector<IntegerValue> normalized_objective_coefficients_;
179
180 // Temporary vector to store cores.
181 std::vector<std::vector<Literal>> temp_cores_;
182};
183
184} // namespace sat
185} // namespace operations_research
186
187#endif // OR_TOOLS_SAT_MAX_HS_H_
STL vector ---------------------------------------------------------------—.
HittingSetOptimizer(const CpModelProto &model_proto, const ObjectiveDefinition &objective_definition, const std::function< void()> &feasible_solution_observer, Model *model)
Definition max_hs.cc:66
const CpModelProto *const model_proto
These are never nullptr.
const Constraint * ct
IntVar * var
GRBmodel * model
In SWIG mode, we don't want anything besides these top-level includes.