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