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