Google OR-Tools v9.9
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
sat_solver.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// This file implements a SAT solver.
15// see http://en.wikipedia.org/wiki/Boolean_satisfiability_problem
16// for more detail.
17// TODO(user): Expand.
18
19#ifndef OR_TOOLS_SAT_SAT_SOLVER_H_
20#define OR_TOOLS_SAT_SAT_SOLVER_H_
21
22#include <cstdint>
23#include <functional>
24#include <limits>
25#include <memory>
26#include <ostream>
27#include <string>
28#include <utility>
29#include <vector>
30
31#include "absl/base/attributes.h"
32#include "absl/container/flat_hash_map.h"
33#include "absl/log/check.h"
34#include "absl/strings/string_view.h"
35#include "absl/types/span.h"
36#include "ortools/base/hash.h"
38#include "ortools/base/timer.h"
39#include "ortools/base/types.h"
40#include "ortools/sat/clause.h"
42#include "ortools/sat/model.h"
44#include "ortools/sat/restart.h"
47#include "ortools/sat/sat_parameters.pb.h"
48#include "ortools/util/bitset.h"
50#include "ortools/util/stats.h"
53
54namespace operations_research {
55namespace sat {
56
57// A constant used by the EnqueueDecision*() API.
58const int kUnsatTrailIndex = -1;
59
60// The main SAT solver.
61// It currently implements the CDCL algorithm. See
62// http://en.wikipedia.org/wiki/Conflict_Driven_Clause_Learning
63class SatSolver {
64 public:
65 SatSolver();
66 explicit SatSolver(Model* model);
67
68 // This type is neither copyable nor movable.
69 SatSolver(const SatSolver&) = delete;
70 SatSolver& operator=(const SatSolver&) = delete;
71
72 ~SatSolver();
73
74 // TODO(user): Remove. This is temporary for accessing the model deep within
75 // some old code that didn't use the Model object.
76 Model* model() { return model_; }
77
78 // Parameters management. Note that calling SetParameters() will reset the
79 // value of many heuristics. For instance:
80 // - The restart strategy will be reinitialized.
81 // - The random seed and random generator will be reset to the value given in
82 // parameters.
83 // - The global TimeLimit singleton will be reset and time will be
84 // counted from this call.
85 void SetParameters(const SatParameters& parameters);
86 const SatParameters& parameters() const;
87
88 // Increases the number of variables of the current problem.
89 //
90 // TODO(user): Rename to IncreaseNumVariablesTo() until we support removing
91 // variables...
92 void SetNumVariables(int num_variables);
93 int NumVariables() const { return num_variables_.value(); }
94 BooleanVariable NewBooleanVariable() {
95 const int num_vars = NumVariables();
96
97 // We need to be able to encode the variable as a literal.
98 CHECK_LT(2 * num_vars, std::numeric_limits<int32_t>::max());
99 SetNumVariables(num_vars + 1);
100 return BooleanVariable(num_vars);
101 }
102
103 // Fixes a variable so that the given literal is true. This can be used to
104 // solve a subproblem where some variables are fixed. Note that it is more
105 // efficient to add such unit clause before all the others.
106 // Returns false if the problem is detected to be UNSAT.
107 ABSL_MUST_USE_RESULT bool AddUnitClause(Literal true_literal);
108
109 // Same as AddProblemClause() below, but for small clauses.
112
113 // Adds a clause to the problem. Returns false if the problem is detected to
114 // be UNSAT.
115 // If is_safe is false, we will do some basic presolving like removing
116 // duplicate literals.
117 //
118 // TODO(user): Rename this to AddClause(), also get rid of the specialized
119 // AddUnitClause(), AddBinaryClause() and AddTernaryClause() since they
120 // just end up calling this?
121 bool AddProblemClause(absl::Span<const Literal> literals,
122 bool is_safe = true);
123
124 // Adds a pseudo-Boolean constraint to the problem. Returns false if the
125 // problem is detected to be UNSAT. If the constraint is always true, this
126 // detects it and does nothing.
127 //
128 // Note(user): There is an optimization if the same constraint is added
129 // consecutively (even if the bounds are different). This is particularly
130 // useful for an optimization problem when we want to constrain the objective
131 // of the problem more and more. Just re-adding such constraint is relatively
132 // efficient.
133 //
134 // OVERFLOW: The sum of the absolute value of all the coefficients
135 // in the constraint must not overflow. This is currently CHECKed().
136 // TODO(user): Instead of failing, implement an error handling code.
137 bool AddLinearConstraint(bool use_lower_bound, Coefficient lower_bound,
138 bool use_upper_bound, Coefficient upper_bound,
139 std::vector<LiteralWithCoeff>* cst);
140
141 // Returns true if the model is UNSAT. Note that currently the status is
142 // "sticky" and once this happen, nothing else can be done with the solver.
143 //
144 // Thanks to this function, a client can safely ignore the return value of any
145 // Add*() functions. If one of them return false, then ModelIsUnsat() will
146 // return true.
147 bool ModelIsUnsat() const { return model_is_unsat_; }
148
149 // TODO(user): remove this function.
150 bool IsModelUnsat() const { return model_is_unsat_; } // DEPRECATED
151
152 // Adds and registers the given propagator with the sat solver. Note that
153 // during propagation, they will be called in the order they were added.
154 void AddPropagator(SatPropagator* propagator);
155 void AddLastPropagator(SatPropagator* propagator);
156 void TakePropagatorOwnership(std::unique_ptr<SatPropagator> propagator) {
157 owned_propagators_.push_back(std::move(propagator));
158 }
159
160 // Wrapper around the same functions in SatDecisionPolicy.
161 //
162 // TODO(user): Clean this up by making clients directly talk to
163 // SatDecisionPolicy.
167 std::vector<std::pair<Literal, float>> AllPreferences() const {
168 return decision_policy_->AllPreferences();
169 }
171 return decision_policy_->ResetDecisionHeuristic();
172 }
173
174 // Solves the problem and returns its status.
175 // An empty problem is considered to be SAT.
176 //
177 // Note that the conflict limit applies only to this function and starts
178 // counting from the time it is called.
179 //
180 // This will restart from the current solver configuration. If a previous call
181 // to Solve() was interrupted by a conflict or time limit, calling this again
182 // will resume the search exactly as it would have continued.
183 //
184 // Note that this will use the TimeLimit singleton, so the time limit
185 // will be counted since the last time TimeLimit was reset, not from
186 // the start of this function.
193 Status Solve();
194
195 // Same as Solve(), but with a given time limit. Note that this will not
196 // update the TimeLimit singleton, but only the passed object instead.
198
199 // Simple interface to solve a problem under the given assumptions. This
200 // simply ask the solver to solve a problem given a set of variables fixed to
201 // a given value (the assumptions). Compared to simply calling AddUnitClause()
202 // and fixing the variables once and for all, this allow to backtrack over the
203 // assumptions and thus exploit the incrementally between subsequent solves.
204 //
205 // This function backtrack over all the current decision, tries to enqueue the
206 // given assumptions, sets the assumption level accordingly and finally calls
207 // Solve().
208 //
209 // If, given these assumptions, the model is UNSAT, this returns the
210 // ASSUMPTIONS_UNSAT status. INFEASIBLE is reserved for the case where the
211 // model is proven to be unsat without any assumptions.
212 //
213 // If ASSUMPTIONS_UNSAT is returned, it is possible to get a "core" of unsat
214 // assumptions by calling GetLastIncompatibleDecisions().
216 const std::vector<Literal>& assumptions,
217 int64_t max_number_of_conflicts = -1);
218
219 // Changes the assumption level. All the decisions below this level will be
220 // treated as assumptions by the next Solve(). Note that this may impact some
221 // heuristics, like the LBD value of a clause.
222 void SetAssumptionLevel(int assumption_level);
223
224 // Returns the current assumption level. Note that if a solve was done since
225 // the last SetAssumptionLevel(), then the returned level may be lower than
226 // the one that was set. This is because some assumptions may now be
227 // consequences of others before them due to the newly learned clauses.
228 int AssumptionLevel() const { return assumption_level_; }
229
230 // This can be called just after SolveWithAssumptions() returned
231 // ASSUMPTION_UNSAT or after EnqueueDecisionAndBacktrackOnConflict() leaded
232 // to a conflict. It returns a subsequence (in the correct order) of the
233 // previously enqueued decisions that cannot be taken together without making
234 // the problem UNSAT.
235 std::vector<Literal> GetLastIncompatibleDecisions();
236
237 // Advanced usage. The next 3 functions allow to drive the search from outside
238 // the solver.
239
240 // Takes a new decision (the given true_literal must be unassigned) and
241 // propagates it. Returns the trail index of the first newly propagated
242 // literal. If there is a conflict and the problem is detected to be UNSAT,
243 // returns kUnsatTrailIndex.
244 //
245 // Important: In the presence of assumptions, this also returns
246 // kUnsatTrailIndex on ASSUMPTION_UNSAT. One can know the difference with
247 // IsModelUnsat().
248 //
249 // A client can determine if there is a conflict by checking if the
250 // CurrentDecisionLevel() was increased by 1 or not.
251 //
252 // If there is a conflict, the given decision is not applied and:
253 // - The conflict is learned.
254 // - The decisions are potentially backtracked to the first decision that
255 // propagates more variables because of the newly learned conflict.
256 // - The returned value is equal to trail_->Index() after this backtracking
257 // and just before the new propagation (due to the conflict) which is also
258 // performed by this function.
260
261 // This function starts by calling EnqueueDecisionAndBackjumpOnConflict(). If
262 // there is no conflict, it stops there. Otherwise, it tries to reapply all
263 // the decisions that were backjumped over until the first one that can't be
264 // taken because it is incompatible. Note that during this process, more
265 // conflicts may happen and the trail may be backtracked even further.
266 //
267 // In any case, the new decisions stack will be the largest valid "prefix"
268 // of the old stack. Note that decisions that are now consequence of the ones
269 // before them will no longer be decisions.
270 //
271 // Returns INFEASIBLE if the model was proven infeasible, ASSUMPTION_UNSAT if
272 // the current decision and the one we are trying to take are not compatible
273 // together and FEASIBLE if all decisions are taken.
274 //
275 // Note(user): This function can be called with an already assigned literal.
277 Literal true_literal, int* first_propagation_index = nullptr);
278
279 // Tries to enqueue the given decision and performs the propagation.
280 // Returns true if no conflict occurred. Otherwise, returns false and restores
281 // the solver to the state just before this was called.
282 //
283 // Note(user): With this function, the solver doesn't learn anything.
284 bool EnqueueDecisionIfNotConflicting(Literal true_literal);
285
286 // Restores the state to the given target decision level. The decision at that
287 // level and all its propagation will not be undone. But all the trail after
288 // this will be cleared. Calling this with 0 will revert all the decisions and
289 // only the fixed variables will be left on the trail.
290 void Backtrack(int target_level);
291
292 // Advanced usage. This is meant to restore the solver to a "proper" state
293 // after a solve was interrupted due to a limit reached.
294 //
295 // Without assumption (i.e. if AssumptionLevel() is 0), this will revert all
296 // decisions and make sure that all the fixed literals are propagated. In
297 // presence of assumptions, this will either backtrack to the assumption level
298 // or re-enqueue any assumptions that may have been backtracked over due to
299 // conflits resolution. In both cases, the propagation is finished.
300 //
301 // Note that this may prove the model to be UNSAT or ASSUMPTION_UNSAT in which
302 // case it will return false.
304
305 // Advanced usage. Finish the progation if it was interrupted. Note that this
306 // might run into conflict and will propagate again until a fixed point is
307 // reached or the model was proven UNSAT. Returns IsModelUnsat().
308 ABSL_MUST_USE_RESULT bool FinishPropagation();
309
310 // Like Backtrack(0) but make sure the propagation is finished and return
311 // false if unsat was detected. This also removes any assumptions level.
312 ABSL_MUST_USE_RESULT bool ResetToLevelZero();
313
314 // Changes the assumptions level and the current solver assumptions. Returns
315 // false if the model is UNSAT or ASSUMPTION_UNSAT, true otherwise.
316 //
317 // This uses the "new" assumptions handling, where all assumptions are
318 // enqueued at once at decision level 1 before we start to propagate. This has
319 // many advantages. In particular, because we propagate with the binary
320 // implications first, if we ever have assumption => not(other_assumptions) we
321 // are guaranteed to find it and returns a core of size 2.
322 //
323 // Paper: "Speeding Up Assumption-Based SAT", Randy Hickey and Fahiem Bacchus
324 // http://www.maxhs.org/docs/Hickey-Bacchus2019_Chapter_SpeedingUpAssumption-BasedSAT.pdf
325 bool ResetWithGivenAssumptions(const std::vector<Literal>& assumptions);
326
327 // Advanced usage. If the decision level is smaller than the assumption level,
328 // this will try to reapply all assumptions. Returns true if this was doable,
329 // otherwise returns false in which case the model is either UNSAT or
330 // ASSUMPTION_UNSAT.
332
333 // Helper functions to get the correct status when one of the functions above
334 // returns false.
337 }
338
339 // Extract the current problem clauses. The Output type must support the two
340 // functions:
341 // - void AddBinaryClause(Literal a, Literal b);
342 // - void AddClause(absl::Span<const Literal> clause);
343 //
344 // TODO(user): also copy the removable clauses?
345 template <typename Output>
346 void ExtractClauses(Output* out) {
347 CHECK(!IsModelUnsat());
348 Backtrack(0);
349 if (!FinishPropagation()) return;
350
351 // It is important to process the newly fixed variables, so they are not
352 // present in the clauses we export.
353 if (num_processed_fixed_variables_ < trail_->Index()) {
355 }
356 clauses_propagator_->DeleteRemovedClauses();
357
358 // Note(user): Putting the binary clauses first help because the presolver
359 // currently process the clauses in order.
360 out->SetNumVariables(NumVariables());
361 binary_implication_graph_->ExtractAllBinaryClauses(out);
362 for (SatClause* clause : clauses_propagator_->AllClausesInCreationOrder()) {
363 if (!clauses_propagator_->IsRemovable(clause)) {
364 out->AddClause(clause->AsSpan());
365 }
366 }
367 }
368
369 // Functions to manage the set of learned binary clauses.
370 // Only clauses added/learned when TrackBinaryClause() is true are managed.
371 void TrackBinaryClauses(bool value) { track_binary_clauses_ = value; }
372 bool AddBinaryClauses(const std::vector<BinaryClause>& clauses);
373 const std::vector<BinaryClause>& NewlyAddedBinaryClauses();
375
376 struct Decision {
377 Decision() = default;
379 int trail_index = 0;
381 };
382
383 // Note that the Decisions() vector is always of size NumVariables(), and that
384 // only the first CurrentDecisionLevel() entries have a meaning.
385 const std::vector<Decision>& Decisions() const { return decisions_; }
386 int CurrentDecisionLevel() const { return current_decision_level_; }
387 const Trail& LiteralTrail() const { return *trail_; }
388 const VariablesAssignment& Assignment() const { return trail_->Assignment(); }
389
390 // Some statistics since the creation of the solver.
391 int64_t num_branches() const;
392 int64_t num_failures() const;
393 int64_t num_propagations() const;
394
395 // Note that we count the number of backtrack to level zero from a positive
396 // level. Those can corresponds to actual restarts, or conflicts that learn
397 // unit clauses or any other reason that trigger such backtrack.
398 int64_t num_restarts() const;
399
400 // Access to all counters.
401 // Tracks various information about the solver progress.
402 struct Counters {
403 int64_t num_branches = 0;
404 int64_t num_failures = 0;
405 int64_t num_restarts = 0;
406
407 // Minimization stats.
408 int64_t num_minimizations = 0;
410
411 // PB constraints.
413
414 // Clause learning /deletion stats.
418
419 // TryToMinimizeClause() stats.
426 };
427 Counters counters() const { return counters_; }
428
429 // A deterministic number that should be correlated with the time spent in
430 // the Solve() function. The order of magnitude should be close to the time
431 // in seconds.
432 double deterministic_time() const;
433
434 // Only used for debugging. Save the current assignment in debug_assignment_.
435 // The idea is that if we know that a given assignment is satisfiable, then
436 // all the learned clauses or PB constraints must be satisfiable by it. In
437 // debug mode, and after this is called, all the learned clauses are tested to
438 // satisfy this saved assignment.
439 void SaveDebugAssignment();
440 void LoadDebugSolution(const std::vector<Literal>& solution);
441
442 // Returns true iff the loaded problem only contains clauses.
443 bool ProblemIsPureSat() const { return problem_is_pure_sat_; }
444
445 void SetDratProofHandler(DratProofHandler* drat_proof_handler) {
446 drat_proof_handler_ = drat_proof_handler;
447 clauses_propagator_->SetDratProofHandler(drat_proof_handler_);
448 binary_implication_graph_->SetDratProofHandler(drat_proof_handler_);
449 }
450
451 // This function is here to deal with the case where a SAT/CP model is found
452 // to be trivially UNSAT while the user is constructing the model. Instead of
453 // having to test the status of all the lines adding a constraint, one can
454 // just check if the solver is not UNSAT once the model is constructed. Note
455 // that we usually log a warning on the first constraint that caused a
456 // "trival" unsatisfiability.
457 void NotifyThatModelIsUnsat() { model_is_unsat_ = true; }
458
459 // Adds a clause at any level of the tree and propagate any new deductions.
460 // Returns false if the model becomes UNSAT. Important: We currently do not
461 // support adding a clause that is already falsified at a positive decision
462 // level. Doing that will cause a check fail.
463 //
464 // TODO(user): Backjump and propagate on a falsified clause? this is currently
465 // not needed.
466 bool AddClauseDuringSearch(absl::Span<const Literal> literals);
467
468 // Performs propagation of the recently enqueued elements.
469 // Mainly visible for testing.
470 ABSL_MUST_USE_RESULT bool Propagate();
471
472 bool MinimizeByPropagation(double dtime);
473
474 // Advance the given time limit with all the deterministic time that was
475 // elapsed since last call.
477 const double current = deterministic_time();
479 current - deterministic_time_at_last_advanced_time_limit_);
480 deterministic_time_at_last_advanced_time_limit_ = current;
481 }
482
483 // Simplifies the problem when new variables are assigned at level 0.
485
486 int64_t NumFixedVariables() const {
487 if (!decisions_.empty()) return decisions_[0].trail_index;
488 CHECK_EQ(CurrentDecisionLevel(), 0);
489 return trail_->Index();
490 }
491
492 // Hack to allow to temporarily disable logging if it is enabled.
493 SolverLogger* mutable_logger() { return logger_; }
494
495 // Processes the current conflict from trail->FailingClause().
496 //
497 // This learns the conflict, backtracks, enqueues the consequence of the
498 // learned conflict and return. When handling assumptions, this might return
499 // false without backtracking in case of ASSUMPTIONS_UNSAT. This is only
500 // exposed to allow processing a conflict detected outside normal propagation.
502
503 private:
504 // All Solve() functions end up calling this one.
505 Status SolveInternal(TimeLimit* time_limit, int64_t max_number_of_conflicts);
506
507 // Adds a binary clause to the BinaryImplicationGraph and to the
508 // BinaryClauseManager when track_binary_clauses_ is true.
509 void AddBinaryClauseInternal(Literal a, Literal b);
510
511 // See SaveDebugAssignment(). Note that these functions only consider the
512 // variables at the time the debug_assignment_ was saved. If new variables
513 // were added since that time, they will be considered unassigned.
514 bool ClauseIsValidUnderDebugAssignment(
515 absl::Span<const Literal> clause) const;
516 bool PBConstraintIsValidUnderDebugAssignment(
517 const std::vector<LiteralWithCoeff>& cst, Coefficient rhs) const;
518
519 // Logs the given status if parameters_.log_search_progress() is true.
520 // Also returns it.
521 Status StatusWithLog(Status status);
522
523 // Main function called from SolveWithAssumptions() or from Solve() with an
524 // assumption_level of 0 (meaning no assumptions).
525 Status SolveInternal(int assumption_level);
526
527 // Applies the previous decisions (which are still on decisions_), in order,
528 // starting from the one at the current decision level. Stops at the one at
529 // decisions_[level] or on the first decision already propagated to "false"
530 // and thus incompatible.
531 //
532 // Note that during this process, conflicts may arise which will lead to
533 // backjumps. In this case, we will simply keep reapplying decisions from the
534 // last one backtracked over and so on.
535 //
536 // Returns FEASIBLE if no conflict occurred, INFEASIBLE if the model was
537 // proven unsat and ASSUMPTION_UNSAT otherwise. In the last case the first non
538 // taken old decision will be propagated to false by the ones before.
539 //
540 // first_propagation_index will be filled with the trail index of the first
541 // newly propagated literal, or with -1 if INFEASIBLE is returned.
542 Status ReapplyDecisionsUpTo(int level,
543 int* first_propagation_index = nullptr);
544
545 // Returns false if the thread memory is over the limit.
546 bool IsMemoryLimitReached() const;
547
548 // Sets model_is_unsat_ to true and return false.
549 bool SetModelUnsat();
550
551 // Returns the decision level of a given variable.
552 int DecisionLevel(BooleanVariable var) const {
553 return trail_->Info(var).level;
554 }
555
556 // Returns the relevant pointer if the given variable was propagated by the
557 // constraint in question. This is used to bump the activity of the learned
558 // clauses or pb constraints.
559 SatClause* ReasonClauseOrNull(BooleanVariable var) const;
560 UpperBoundedLinearConstraint* ReasonPbConstraintOrNull(
561 BooleanVariable var) const;
562
563 // This does one step of a pseudo-Boolean resolution:
564 // - The variable var has been assigned to l at a given trail_index.
565 // - The reason for var propagates it to l.
566 // - The conflict propagates it to not(l)
567 // The goal of the operation is to combine the two constraints in order to
568 // have a new conflict at a lower trail_index.
569 //
570 // Returns true if the reason for var was a normal clause. In this case,
571 // the *slack is updated to its new value.
572 bool ResolvePBConflict(BooleanVariable var,
573 MutableUpperBoundedLinearConstraint* conflict,
574 Coefficient* slack);
575
576 // Returns true iff the clause is the reason for an assigned variable.
577 //
578 // TODO(user): With our current data structures, we could also return true
579 // for clauses that were just used as a reason (like just before an untrail).
580 // This may be beneficial, but should properly be defined so that we can
581 // have the same behavior if we change the implementation.
582 bool ClauseIsUsedAsReason(SatClause* clause) const {
583 const BooleanVariable var = clause->PropagatedLiteral().Variable();
584 return trail_->Info(var).trail_index < trail_->Index() &&
585 (*trail_)[trail_->Info(var).trail_index].Variable() == var &&
586 ReasonClauseOrNull(var) == clause;
587 }
588
589 // Add a problem clause. The clause is assumed to be "cleaned", that is no
590 // duplicate variables (not strictly required) and not empty.
591 bool AddProblemClauseInternal(absl::Span<const Literal> literals);
592
593 // This is used by all the Add*LinearConstraint() functions. It detects
594 // infeasible/trivial constraints or clause constraints and takes the proper
595 // action.
596 bool AddLinearConstraintInternal(const std::vector<LiteralWithCoeff>& cst,
597 Coefficient rhs, Coefficient max_value);
598
599 // Makes sure a pseudo boolean constraint is in canonical form.
600 void CanonicalizeLinear(std::vector<LiteralWithCoeff>* cst,
601 Coefficient* bound_shift, Coefficient* max_value);
602
603 // Adds a learned clause to the problem. This should be called after
604 // Backtrack(). The backtrack is such that after it is applied, all the
605 // literals of the learned close except one will be false. Thus the last one
606 // will be implied True. This function also Enqueue() the implied literal.
607 //
608 // Returns the LBD of the clause.
609 int AddLearnedClauseAndEnqueueUnitPropagation(
610 const std::vector<Literal>& literals, bool is_redundant);
611
612 // Creates a new decision which corresponds to setting the given literal to
613 // True and Enqueue() this change.
614 void EnqueueNewDecision(Literal literal);
615
616 // Returns true if everything has been propagated.
617 //
618 // TODO(user): This test is fast but not exhaustive, especially regarding the
619 // integer propagators. Fix.
620 bool PropagationIsDone() const;
621
622 // Update the propagators_ list with the relevant propagators.
623 void InitializePropagators();
624
625 // Output to the DRAT proof handler any newly fixed variables.
626 void ProcessNewlyFixedVariablesForDratProof();
627
628 // Returns the maximum trail_index of the literals in the given clause.
629 // All the literals must be assigned. Returns -1 if the clause is empty.
630 int ComputeMaxTrailIndex(absl::Span<const Literal> clause) const;
631
632 // Computes what is known as the first UIP (Unique implication point) conflict
633 // clause starting from the failing clause. For a definition of UIP and a
634 // comparison of the different possible conflict clause computation, see the
635 // reference below.
636 //
637 // The conflict will have only one literal at the highest decision level, and
638 // this literal will always be the first in the conflict vector.
639 //
640 // L Zhang, CF Madigan, MH Moskewicz, S Malik, "Efficient conflict driven
641 // learning in a boolean satisfiability solver" Proceedings of the 2001
642 // IEEE/ACM international conference on Computer-aided design, Pages 279-285.
643 // http://www.cs.tau.ac.il/~msagiv/courses/ATP/iccad2001_final.pdf
644 void ComputeFirstUIPConflict(
645 int max_trail_index, std::vector<Literal>* conflict,
646 std::vector<Literal>* reason_used_to_infer_the_conflict,
647 std::vector<SatClause*>* subsumed_clauses);
648
649 // Fills literals with all the literals in the reasons of the literals in the
650 // given input. The output vector will have no duplicates and will not contain
651 // the literals already present in the input.
652 void ComputeUnionOfReasons(const std::vector<Literal>& input,
653 std::vector<Literal>* literals);
654
655 // Do the full pseudo-Boolean constraint analysis. This calls multiple
656 // time ResolvePBConflict() on the current conflict until we have a conflict
657 // that allow us to propagate more at a lower decision level. This level
658 // is the one returned in backjump_level.
659 void ComputePBConflict(int max_trail_index, Coefficient initial_slack,
660 MutableUpperBoundedLinearConstraint* conflict,
661 int* backjump_level);
662
663 // Applies some heuristics to a conflict in order to minimize its size and/or
664 // replace literals by other literals from lower decision levels. The first
665 // function choose which one of the other functions to call depending on the
666 // parameters.
667 //
668 // Precondition: is_marked_ should be set to true for all the variables of
669 // the conflict. It can also contains false non-conflict variables that
670 // are implied by the negation of the 1-UIP conflict literal.
671 void MinimizeConflict(std::vector<Literal>* conflict);
672 void MinimizeConflictExperimental(std::vector<Literal>* conflict);
673 void MinimizeConflictSimple(std::vector<Literal>* conflict);
674 void MinimizeConflictRecursively(std::vector<Literal>* conflict);
675
676 // Utility function used by MinimizeConflictRecursively().
677 bool CanBeInferedFromConflictVariables(BooleanVariable variable);
678
679 // To be used in DCHECK(). Verifies some property of the conflict clause:
680 // - There is an unique literal with the highest decision level.
681 // - This literal appears in the first position.
682 // - All the other literals are of smaller decision level.
683 // - There is no literal with a decision level of zero.
684 bool IsConflictValid(const std::vector<Literal>& literals);
685
686 // Given the learned clause after a conflict, this computes the correct
687 // backtrack level to call Backtrack() with.
688 int ComputeBacktrackLevel(const std::vector<Literal>& literals);
689
690 // The LBD (Literal Blocks Distance) is the number of different decision
691 // levels at which the literals of the clause were assigned. Note that we
692 // ignore the decision level 0 whereas the definition in the paper below
693 // doesn't:
694 //
695 // G. Audemard, L. Simon, "Predicting Learnt Clauses Quality in Modern SAT
696 // Solver" in Twenty-first International Joint Conference on Artificial
697 // Intelligence (IJCAI'09), july 2009.
698 // http://www.ijcai.org/papers09/Papers/IJCAI09-074.pdf
699 //
700 // IMPORTANT: All the literals of the clause must be assigned, and the first
701 // literal must be of the highest decision level. This will be the case for
702 // all the reason clauses.
703 template <typename LiteralList>
704 int ComputeLbd(const LiteralList& literals);
705
706 // Checks if we need to reduce the number of learned clauses and do
707 // it if needed. Also updates the learned clause limit for the next cleanup.
708 void CleanClauseDatabaseIfNeeded();
709
710 // Activity management for clauses. This work the same way at the ones for
711 // variables, but with different parameters.
712 void BumpReasonActivities(const std::vector<Literal>& literals);
713 void BumpClauseActivity(SatClause* clause);
714 void RescaleClauseActivities(double scaling_factor);
715 void UpdateClauseActivityIncrement();
716
717 std::string DebugString(const SatClause& clause) const;
718 std::string StatusString(Status status) const;
719 std::string RunningStatisticsString() const;
720
721 // Marks as "non-deletable" all clauses that were used to infer the given
722 // variable. The variable must be currently assigned.
723 void KeepAllClauseUsedToInfer(BooleanVariable variable);
724 bool SubsumptionIsInteresting(BooleanVariable variable);
725
726 // Use propagation to try to minimize the given clause. This is really similar
727 // to MinimizeCoreWithPropagation(). It must be called when the current
728 // decision level is zero. Note that because this do a small tree search, it
729 // will impact the variable/clauses activities and may add new conflicts.
730 void TryToMinimizeClause(SatClause* clause);
731
732 // This is used by the old non-model constructor.
733 Model* model_;
734 std::unique_ptr<Model> owned_model_;
735
736 BooleanVariable num_variables_ = BooleanVariable(0);
737
738 // Internal propagators. We keep them here because we need more than the
739 // SatPropagator interface for them.
740 BinaryImplicationGraph* binary_implication_graph_;
741 ClauseManager* clauses_propagator_;
742 PbConstraints* pb_constraints_;
743
744 // Ordered list of propagators used by Propagate()/Untrail().
745 std::vector<SatPropagator*> propagators_;
746 std::vector<SatPropagator*> non_empty_propagators_;
747
748 // Ordered list of propagators added with AddPropagator().
749 std::vector<SatPropagator*> external_propagators_;
750 SatPropagator* last_propagator_ = nullptr;
751
752 // For the old, non-model interface.
753 std::vector<std::unique_ptr<SatPropagator>> owned_propagators_;
754
755 // Keep track of all binary clauses so they can be exported.
756 bool track_binary_clauses_;
757 BinaryClauseManager binary_clauses_;
758
759 // Pointers to singleton Model objects.
760 Trail* trail_;
761 TimeLimit* time_limit_;
762 SatParameters* parameters_;
763 RestartPolicy* restart_;
764 SatDecisionPolicy* decision_policy_;
765 SolverLogger* logger_;
766
767 // Used for debugging only. See SaveDebugAssignment().
768 VariablesAssignment debug_assignment_;
769
770 // The stack of decisions taken by the solver. They are stored in [0,
771 // current_decision_level_). The vector is of size num_variables_ so it can
772 // store all the decisions. This is done this way because in some situation we
773 // need to remember the previously taken decisions after a backtrack.
774 int current_decision_level_ = 0;
775 std::vector<Decision> decisions_;
776
777 // The trail index after the last Backtrack() call or before the last
778 // EnqueueNewDecision() call.
779 int last_decision_or_backtrack_trail_index_ = 0;
780
781 // The assumption level. See SolveWithAssumptions().
782 int assumption_level_ = 0;
783 std::vector<Literal> assumptions_;
784
785 // The size of the trail when ProcessNewlyFixedVariables() was last called.
786 // Note that the trail contains only fixed literals (that is literals of
787 // decision levels 0) before this point.
788 int num_processed_fixed_variables_ = 0;
789 double deterministic_time_of_last_fixed_variables_cleanup_ = 0.0;
790
791 // Used in ProcessNewlyFixedVariablesForDratProof().
792 int drat_num_processed_fixed_variables_ = 0;
793
794 Counters counters_;
795
796 // Solver information.
797 WallTimer timer_;
798
799 // This is set to true if the model is found to be UNSAT when adding new
800 // constraints.
801 bool model_is_unsat_ = false;
802
803 // Increment used to bump the variable activities.
804 double clause_activity_increment_;
805
806 // This counter is decremented each time we learn a clause that can be
807 // deleted. When it reaches zero, a clause cleanup is triggered.
808 int num_learned_clause_before_cleanup_ = 0;
809
810 int64_t minimization_by_propagation_threshold_ = 0;
811
812 // Temporary members used during conflict analysis.
813 SparseBitset<BooleanVariable> is_marked_;
814 SparseBitset<BooleanVariable> is_independent_;
815 SparseBitset<BooleanVariable> tmp_mark_;
816 std::vector<int> min_trail_index_per_level_;
817
818 // Temporary members used by CanBeInferedFromConflictVariables().
819 std::vector<BooleanVariable> dfs_stack_;
820 std::vector<BooleanVariable> variable_to_process_;
821
822 // Temporary member used when adding clauses.
823 std::vector<Literal> literals_scratchpad_;
824
825 // A boolean vector used to temporarily mark decision levels.
826 DEFINE_STRONG_INDEX_TYPE(SatDecisionLevel);
827 SparseBitset<SatDecisionLevel> is_level_marked_;
828
829 // Temporary vectors used by EnqueueDecisionAndBackjumpOnConflict().
830 std::vector<Literal> learned_conflict_;
831 std::vector<Literal> reason_used_to_infer_the_conflict_;
832 std::vector<Literal> extra_reason_literals_;
833 std::vector<SatClause*> subsumed_clauses_;
834
835 // When true, temporarily disable the deletion of clauses that are not needed
836 // anymore. This is a hack for TryToMinimizeClause() because we use
837 // propagation in this function which might trigger a clause database
838 // deletion, but we still want the pointer to the clause we wants to minimize
839 // to be valid until the end of that function.
840 bool block_clause_deletion_ = false;
841
842 // "cache" to avoid inspecting many times the same reason during conflict
843 // analysis.
844 VariableWithSameReasonIdentifier same_reason_identifier_;
845
846 // Boolean used to include/exclude constraints from the core computation.
847 bool is_relevant_for_core_computation_;
848
849 // The current pseudo-Boolean conflict used in PB conflict analysis.
850 MutableUpperBoundedLinearConstraint pb_conflict_;
851
852 // The deterministic time when the time limit was updated.
853 // As the deterministic time in the time limit has to be advanced manually,
854 // it is necessary to keep track of the last time the time was advanced.
855 double deterministic_time_at_last_advanced_time_limit_ = 0;
856
857 // This is true iff the loaded problem only contains clauses.
858 bool problem_is_pure_sat_;
859
860 DratProofHandler* drat_proof_handler_;
861
862 mutable StatsGroup stats_;
863};
864
865// Tries to minimize the given UNSAT core with a really simple heuristic.
866// The idea is to remove literals that are consequences of others in the core.
867// We already know that in the initial order, no literal is propagated by the
868// one before it, so we just look for propagation in the reverse order.
869//
870// Important: The given SatSolver must be the one that just produced the given
871// core.
872//
873// TODO(user): One should use MinimizeCoreWithPropagation() instead.
874void MinimizeCore(SatSolver* solver, std::vector<Literal>* core);
875
876// ============================================================================
877// Model based functions.
878//
879// TODO(user): move them in another file, and unit-test them.
880// ============================================================================
881
882inline std::function<void(Model*)> BooleanLinearConstraint(
883 int64_t lower_bound, int64_t upper_bound,
884 std::vector<LiteralWithCoeff>* cst) {
885 return [=](Model* model) {
886 model->GetOrCreate<SatSolver>()->AddLinearConstraint(
887 /*use_lower_bound=*/true, Coefficient(lower_bound),
888 /*use_upper_bound=*/true, Coefficient(upper_bound), cst);
889 };
890}
891
892inline std::function<void(Model*)> CardinalityConstraint(
893 int64_t lower_bound, int64_t upper_bound,
894 const std::vector<Literal>& literals) {
895 return [=](Model* model) {
896 std::vector<LiteralWithCoeff> cst;
897 cst.reserve(literals.size());
898 for (int i = 0; i < literals.size(); ++i) {
899 cst.emplace_back(literals[i], 1);
900 }
901 model->GetOrCreate<SatSolver>()->AddLinearConstraint(
902 /*use_lower_bound=*/true, Coefficient(lower_bound),
903 /*use_upper_bound=*/true, Coefficient(upper_bound), &cst);
904 };
905}
906
907inline std::function<void(Model*)> ExactlyOneConstraint(
908 const std::vector<Literal>& literals) {
909 return [=](Model* model) {
910 std::vector<LiteralWithCoeff> cst;
911 cst.reserve(literals.size());
912 for (const Literal l : literals) {
913 cst.emplace_back(l, Coefficient(1));
914 }
915 model->GetOrCreate<SatSolver>()->AddLinearConstraint(
916 /*use_lower_bound=*/true, Coefficient(1),
917 /*use_upper_bound=*/true, Coefficient(1), &cst);
918 };
919}
920
921inline std::function<void(Model*)> AtMostOneConstraint(
922 const std::vector<Literal>& literals) {
923 return [=](Model* model) {
924 std::vector<LiteralWithCoeff> cst;
925 cst.reserve(literals.size());
926 for (const Literal l : literals) {
927 cst.emplace_back(l, Coefficient(1));
928 }
929 model->GetOrCreate<SatSolver>()->AddLinearConstraint(
930 /*use_lower_bound=*/false, Coefficient(0),
931 /*use_upper_bound=*/true, Coefficient(1), &cst);
932 };
933}
934
935inline std::function<void(Model*)> ClauseConstraint(
936 absl::Span<const Literal> literals) {
937 return [=](Model* model) {
938 model->GetOrCreate<SatSolver>()->AddProblemClause(literals,
939 /*is_safe=*/false);
940 };
941}
942
943// a => b.
944inline std::function<void(Model*)> Implication(Literal a, Literal b) {
945 return [=](Model* model) {
946 model->GetOrCreate<SatSolver>()->AddBinaryClause(a.Negated(), b);
947 };
948}
949
950// a == b.
951inline std::function<void(Model*)> Equality(Literal a, Literal b) {
952 return [=](Model* model) {
953 model->GetOrCreate<SatSolver>()->AddBinaryClause(a.Negated(), b);
954 model->GetOrCreate<SatSolver>()->AddBinaryClause(a, b.Negated());
955 };
956}
957
958// r <=> (at least one literal is true). This is a reified clause.
959inline std::function<void(Model*)> ReifiedBoolOr(
960 const std::vector<Literal>& literals, Literal r) {
961 return [=](Model* model) {
962 std::vector<Literal> clause;
963 for (const Literal l : literals) {
964 model->Add(Implication(l, r)); // l => r.
965 clause.push_back(l);
966 }
967
968 // All false => r false.
969 clause.push_back(r.Negated());
970 model->Add(ClauseConstraint(clause));
971 };
972}
973
974// enforcement_literals => clause.
975inline std::function<void(Model*)> EnforcedClause(
976 absl::Span<const Literal> enforcement_literals,
977 absl::Span<const Literal> clause) {
978 return [=](Model* model) {
979 std::vector<Literal> tmp;
980 for (const Literal l : enforcement_literals) {
981 tmp.push_back(l.Negated());
982 }
983 for (const Literal l : clause) {
984 tmp.push_back(l);
985 }
986 model->Add(ClauseConstraint(tmp));
987 };
988}
989
990// r <=> (all literals are true).
991//
992// Note(user): we could have called ReifiedBoolOr() with everything negated.
993inline std::function<void(Model*)> ReifiedBoolAnd(
994 const std::vector<Literal>& literals, Literal r) {
995 return [=](Model* model) {
996 std::vector<Literal> clause;
997 for (const Literal l : literals) {
998 model->Add(Implication(r, l)); // r => l.
999 clause.push_back(l.Negated());
1000 }
1001
1002 // All true => r true.
1003 clause.push_back(r);
1004 model->Add(ClauseConstraint(clause));
1005 };
1006}
1007
1008// r <=> (a <= b).
1009inline std::function<void(Model*)> ReifiedBoolLe(Literal a, Literal b,
1010 Literal r) {
1011 return [=](Model* model) {
1012 // r <=> (a <= b) is the same as r <=> not(a=1 and b=0).
1013 // So r <=> a=0 OR b=1.
1014 model->Add(ReifiedBoolOr({a.Negated(), b}, r));
1015 };
1016}
1017
1018// This checks that the variable is fixed.
1019inline std::function<int64_t(const Model&)> Value(Literal l) {
1020 return [=](const Model& model) {
1021 const Trail* trail = model.Get<Trail>();
1022 CHECK(trail->Assignment().VariableIsAssigned(l.Variable()));
1023 return trail->Assignment().LiteralIsTrue(l);
1024 };
1025}
1026
1027// This checks that the variable is fixed.
1028inline std::function<int64_t(const Model&)> Value(BooleanVariable b) {
1029 return [=](const Model& model) {
1030 const Trail* trail = model.Get<Trail>();
1031 CHECK(trail->Assignment().VariableIsAssigned(b));
1032 return trail->Assignment().LiteralIsTrue(Literal(b, true));
1033 };
1034}
1035
1036// This can be used to enumerate all the solutions. After each SAT call to
1037// Solve(), calling this will reset the solver and exclude the current solution
1038// so that the next call to Solve() will give a new solution or UNSAT is there
1039// is no more new solutions.
1040inline std::function<void(Model*)> ExcludeCurrentSolutionAndBacktrack() {
1041 return [=](Model* model) {
1042 SatSolver* sat_solver = model->GetOrCreate<SatSolver>();
1043
1044 // Note that we only exclude the current decisions, which is an efficient
1045 // way to not get the same SAT assignment.
1046 const int current_level = sat_solver->CurrentDecisionLevel();
1047 std::vector<Literal> clause_to_exclude_solution;
1048 clause_to_exclude_solution.reserve(current_level);
1049 for (int i = 0; i < current_level; ++i) {
1050 clause_to_exclude_solution.push_back(
1051 sat_solver->Decisions()[i].literal.Negated());
1052 }
1053 sat_solver->Backtrack(0);
1054 model->Add(ClauseConstraint(clause_to_exclude_solution));
1055 };
1056}
1057
1058// Returns a string representation of a SatSolver::Status.
1060inline std::ostream& operator<<(std::ostream& os, SatSolver::Status status) {
1061 os << SatStatusString(status);
1062 return os;
1063}
1064
1065} // namespace sat
1066} // namespace operations_research
1067
1068#endif // OR_TOOLS_SAT_SAT_SOLVER_H_
void AdvanceDeterministicTime(double deterministic_duration)
Definition time_limit.h:178
void ExtractAllBinaryClauses(Output *out) const
Definition clause.h:697
void SetDratProofHandler(DratProofHandler *drat_proof_handler)
Definition clause.h:717
bool IsRemovable(SatClause *const clause) const
Definition clause.h:222
void SetDratProofHandler(DratProofHandler *drat_proof_handler)
Definition clause.h:242
const std::vector< SatClause * > & AllClausesInCreationOrder() const
Definition clause.h:214
std::vector< std::pair< Literal, float > > AllPreferences() const
Returns the vector of the current assignment preferences.
void SetAssignmentPreference(Literal literal, float weight)
Base class for all the SAT constraints.
Definition sat_base.h:511
Status EnqueueDecisionAndBacktrackOnConflict(Literal true_literal, int *first_propagation_index=nullptr)
bool AddLinearConstraint(bool use_lower_bound, Coefficient lower_bound, bool use_upper_bound, Coefficient upper_bound, std::vector< LiteralWithCoeff > *cst)
Status SolveWithTimeLimit(TimeLimit *time_limit)
void SetDratProofHandler(DratProofHandler *drat_proof_handler)
Definition sat_solver.h:445
bool AddBinaryClauses(const std::vector< BinaryClause > &clauses)
bool AddProblemClause(absl::Span< const Literal > literals, bool is_safe=true)
bool MinimizeByPropagation(double dtime)
const std::vector< BinaryClause > & NewlyAddedBinaryClauses()
SatSolver(const SatSolver &)=delete
This type is neither copyable nor movable.
SolverLogger * mutable_logger()
Hack to allow to temporarily disable logging if it is enabled.
Definition sat_solver.h:493
void SetAssignmentPreference(Literal literal, float weight)
Definition sat_solver.h:164
BooleanVariable NewBooleanVariable()
Definition sat_solver.h:94
void ProcessNewlyFixedVariables()
Simplifies the problem when new variables are assigned at level 0.
bool ResetWithGivenAssumptions(const std::vector< Literal > &assumptions)
int64_t num_branches() const
Some statistics since the creation of the solver.
void LoadDebugSolution(const std::vector< Literal > &solution)
bool ProblemIsPureSat() const
Returns true iff the loaded problem only contains clauses.
Definition sat_solver.h:443
std::vector< Literal > GetLastIncompatibleDecisions()
bool AddBinaryClause(Literal a, Literal b)
Same as AddProblemClause() below, but for small clauses.
int EnqueueDecisionAndBackjumpOnConflict(Literal true_literal)
void Backtrack(int target_level)
const SatParameters & parameters() const
bool EnqueueDecisionIfNotConflicting(Literal true_literal)
bool AddClauseDuringSearch(absl::Span< const Literal > literals)
ABSL_MUST_USE_RESULT bool Propagate()
void SetAssumptionLevel(int assumption_level)
std::vector< std::pair< Literal, float > > AllPreferences() const
Definition sat_solver.h:167
ABSL_MUST_USE_RESULT bool AddUnitClause(Literal true_literal)
bool AddTernaryClause(Literal a, Literal b, Literal c)
void TakePropagatorOwnership(std::unique_ptr< SatPropagator > propagator)
Definition sat_solver.h:156
SatSolver & operator=(const SatSolver &)=delete
void AdvanceDeterministicTime(TimeLimit *limit)
Definition sat_solver.h:476
Status ResetAndSolveWithGivenAssumptions(const std::vector< Literal > &assumptions, int64_t max_number_of_conflicts=-1)
const VariablesAssignment & Assignment() const
Definition sat_solver.h:388
ABSL_MUST_USE_RESULT bool ResetToLevelZero()
void AddLastPropagator(SatPropagator *propagator)
const std::vector< Decision > & Decisions() const
Definition sat_solver.h:385
ABSL_MUST_USE_RESULT bool FinishPropagation()
const Trail & LiteralTrail() const
Definition sat_solver.h:387
void SetNumVariables(int num_variables)
Definition sat_solver.cc:87
void AddPropagator(SatPropagator *propagator)
void SetParameters(const SatParameters &parameters)
const AssignmentInfo & Info(BooleanVariable var) const
Definition sat_base.h:441
const VariablesAssignment & Assignment() const
Definition sat_base.h:440
bool VariableIsAssigned(BooleanVariable var) const
Returns true iff the given variable is assigned.
Definition sat_base.h:184
bool LiteralIsTrue(Literal literal) const
Definition sat_base.h:176
int64_t a
Definition table.cc:44
std::unique_ptr< SharedClausesManager > clauses
int64_t value
IntVar * var
absl::Status status
Definition g_gurobi.cc:44
double upper_bound
double lower_bound
GRBmodel * model
int literal
time_limit
Definition solve.cc:22
double solution
std::function< void(Model *) ReifiedBoolOr)(const std::vector< Literal > &literals, Literal r)
r <=> (at least one literal is true). This is a reified clause.
Definition sat_solver.h:961
std::string SatStatusString(SatSolver::Status status)
Returns a string representation of a SatSolver::Status.
std::function< void(Model *) AtMostOneConstraint)(const std::vector< Literal > &literals)
Definition sat_solver.h:923
std::function< void(Model *) Equality)(IntegerVariable v, int64_t value)
Fix v to a given value.
Definition integer.h:1905
std::function< int64_t(const Model &) Value)(IntegerVariable v)
This checks that the variable is fixed.
Definition integer.h:1868
std::function< void(Model *) ClauseConstraint)(absl::Span< const Literal > literals)
Definition sat_solver.h:937
std::ostream & operator<<(std::ostream &os, const BoolVar &var)
Definition cp_model.cc:89
std::function< void(Model *) ReifiedBoolLe)(Literal a, Literal b, Literal r)
r <=> (a <= b).
std::function< void(Model *) EnforcedClause)(absl::Span< const Literal > enforcement_literals, absl::Span< const Literal > clause)
enforcement_literals => clause.
Definition sat_solver.h:977
std::function< void(Model *) Implication)(const std::vector< Literal > &enforcement_literals, IntegerLiteral i)
a => b.
Definition integer.h:1918
std::function< void(Model *) BooleanLinearConstraint)(int64_t lower_bound, int64_t upper_bound, std::vector< LiteralWithCoeff > *cst)
Definition sat_solver.h:884
std::function< void(Model *) ExactlyOneConstraint)(const std::vector< Literal > &literals)
Definition sat_solver.h:909
const int kUnsatTrailIndex
A constant used by the EnqueueDecision*() API.
Definition sat_solver.h:58
std::function< void(Model *) ReifiedBoolAnd)(const std::vector< Literal > &literals, Literal r)
Definition sat_solver.h:995
void MinimizeCore(SatSolver *solver, std::vector< Literal > *core)
std::function< void(Model *) ExcludeCurrentSolutionAndBacktrack)()
std::function< void(Model *) CardinalityConstraint)(int64_t lower_bound, int64_t upper_bound, const std::vector< Literal > &literals)
Definition sat_solver.h:894
In SWIG mode, we don't want anything besides these top-level includes.
int64_t weight
Definition pack.cc:510
static int input(yyscan_t yyscanner)
#define DEFINE_STRONG_INDEX_TYPE(index_type_name)
int32_t trail_index
The index of this assignment in the trail.
Definition sat_base.h:251
int64_t minimization_num_clauses
TryToMinimizeClause() stats.
Definition sat_solver.h:420
int64_t num_minimizations
Minimization stats.
Definition sat_solver.h:408
int64_t num_literals_learned
Clause learning /deletion stats.
Definition sat_solver.h:415