OR-Tools  9.6
clause.h
Go to the documentation of this file.
1 // Copyright 2010-2022 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 contains the solver internal representation of the clauses and the
15 // classes used for their propagation.
16 
17 #ifndef OR_TOOLS_SAT_CLAUSE_H_
18 #define OR_TOOLS_SAT_CLAUSE_H_
19 
20 #include <cstdint>
21 #include <deque>
22 #include <string>
23 #include <utility>
24 #include <vector>
25 
26 #include "absl/base/attributes.h"
27 #include "absl/container/flat_hash_map.h"
28 #include "absl/container/flat_hash_set.h"
29 #include "absl/container/inlined_vector.h"
30 #include "absl/random/bit_gen_ref.h"
31 #include "absl/types/span.h"
32 #include "ortools/base/hash.h"
34 #include "ortools/base/logging.h"
35 #include "ortools/base/macros.h"
38 #include "ortools/sat/model.h"
39 #include "ortools/sat/sat_base.h"
40 #include "ortools/sat/sat_parameters.pb.h"
41 #include "ortools/sat/util.h"
42 #include "ortools/util/bitset.h"
43 #include "ortools/util/stats.h"
46 
47 namespace operations_research {
48 namespace sat {
49 
50 // This is how the SatSolver stores a clause. A clause is just a disjunction of
51 // literals. In many places, we just use vector<literal> to encode one. But in
52 // the critical propagation code, we use this class to remove one memory
53 // indirection.
54 class SatClause {
55  public:
56  // Creates a sat clause. There must be at least 2 literals.
57  // Clause with one literal fix variable directly and are never constructed.
58  // Note that in practice, we use BinaryImplicationGraph for the clause of size
59  // 2, so this is used for size at least 3.
60  static SatClause* Create(absl::Span<const Literal> literals);
61 
62  // Non-sized delete because this is a tail-padded class.
63  void operator delete(void* p) {
64  ::operator delete(p); // non-sized delete
65  }
66 
67  // Number of literals in the clause.
68  int size() const { return size_; }
69  int empty() const { return size_ == 0; }
70 
71  // Allows for range based iteration: for (Literal literal : clause) {}.
72  const Literal* const begin() const { return &(literals_[0]); }
73  const Literal* const end() const { return &(literals_[size_]); }
74 
75  // Returns the first and second literals. These are always the watched
76  // literals if the clause is attached in the LiteralWatchers.
77  Literal FirstLiteral() const { return literals_[0]; }
78  Literal SecondLiteral() const { return literals_[1]; }
79 
80  // Returns the literal that was propagated to true. This only works for a
81  // clause that just propagated this literal. Otherwise, this will just returns
82  // a literal of the clause.
83  Literal PropagatedLiteral() const { return literals_[0]; }
84 
85  // Returns the reason for the last unit propagation of this clause. The
86  // preconditions are the same as for PropagatedLiteral(). Note that we don't
87  // need to include the propagated literal.
88  absl::Span<const Literal> PropagationReason() const {
89  return absl::Span<const Literal>(&(literals_[1]), size_ - 1);
90  }
91 
92  // Returns a Span<> representation of the clause.
93  absl::Span<const Literal> AsSpan() const {
94  return absl::Span<const Literal>(&(literals_[0]), size_);
95  }
96 
97  // Removes literals that are fixed. This should only be called at level 0
98  // where a literal is fixed iff it is assigned. Aborts and returns true if
99  // they are not all false.
100  //
101  // Note that the removed literal can still be accessed in the portion [size,
102  // old_size) of literals().
104 
105  // Returns true if the clause is satisfied for the given assignment. Note that
106  // the assignment may be partial, so false does not mean that the clause can't
107  // be satisfied by completing the assignment.
108  bool IsSatisfied(const VariablesAssignment& assignment) const;
109 
110  // Returns true if the clause is attached to a LiteralWatchers.
111  bool IsAttached() const { return size_ > 0; }
112 
113  std::string DebugString() const;
114 
115  private:
116  // LiteralWatchers needs to permute the order of literals in the clause and
117  // call Clear()/Rewrite.
118  friend class LiteralWatchers;
119 
120  Literal* literals() { return &(literals_[0]); }
121 
122  // Marks the clause so that the next call to CleanUpWatchers() can identify it
123  // and actually detach it. We use size_ = 0 for this since the clause will
124  // never be used afterwards.
125  void Clear() { size_ = 0; }
126 
127  // Rewrites a clause with another shorter one. Note that the clause shouldn't
128  // be attached when this is called.
129  void Rewrite(absl::Span<const Literal> new_clause) {
130  size_ = 0;
131  for (const Literal l : new_clause) literals_[size_++] = l;
132  }
133 
134  int32_t size_;
135 
136  // This class store the literals inline, and literals_ mark the starts of the
137  // variable length portion.
138  Literal literals_[0];
139 
140  DISALLOW_COPY_AND_ASSIGN(SatClause);
141 };
142 
143 // Clause information used for the clause database management. Note that only
144 // the clauses that can be removed have an info. The problem clauses and
145 // the learned one that we wants to keep forever do not have one.
146 struct ClauseInfo {
147  double activity = 0.0;
148  int32_t lbd = 0;
150 };
151 
153 
154 // Stores the 2-watched literals data structure. See
155 // http://www.cs.berkeley.edu/~necula/autded/lecture24-sat.pdf for
156 // detail.
157 //
158 // This class is also responsible for owning the clause memory and all related
159 // information.
160 //
161 // TODO(user): Rename ClauseManager. This does more than just watching the
162 // clauses and is the place where all the clauses are stored.
164  public:
165  explicit LiteralWatchers(Model* model);
166  ~LiteralWatchers() override;
167 
168  // Must be called before adding clauses referring to such variables.
169  void Resize(int num_variables);
170 
171  // SatPropagator API.
172  bool Propagate(Trail* trail) final;
173  absl::Span<const Literal> Reason(const Trail& trail,
174  int trail_index) const final;
175 
176  // Returns the reason of the variable at given trail_index. This only works
177  // for variable propagated by this class and is almost the same as Reason()
178  // with a different return format.
179  SatClause* ReasonClause(int trail_index) const;
180 
181  // Adds a new clause and perform initial propagation for this clause only.
182  bool AddClause(absl::Span<const Literal> literals, Trail* trail);
183  bool AddClause(absl::Span<const Literal> literals);
184 
185  // Same as AddClause() for a removable clause. This is only called on learned
186  // conflict, so this should never have all its literal at false (CHECKED).
187  SatClause* AddRemovableClause(const std::vector<Literal>& literals,
188  Trail* trail);
189 
190  // Lazily detach the given clause. The deletion will actually occur when
191  // CleanUpWatchers() is called. The later needs to be called before any other
192  // function in this class can be called. This is DCHECKed.
193  //
194  // Note that we remove the clause from clauses_info_ right away.
195  void LazyDetach(SatClause* clause);
196  void CleanUpWatchers();
197 
198  // Detaches the given clause right away.
199  //
200  // TODO(user): It might be better to have a "slower" mode in
201  // PropagateOnFalse() that deal with detached clauses in the watcher list and
202  // is activated until the next CleanUpWatchers() calls.
203  void Detach(SatClause* clause);
204 
205  // Attaches the given clause. The first two literal of the clause must
206  // be unassigned and the clause must not be already attached.
207  void Attach(SatClause* clause, Trail* trail);
208 
209  // Reclaims the memory of the lazily removed clauses (their size was set to
210  // zero) and remove them from AllClausesInCreationOrder() this work in
211  // O(num_clauses()).
212  void DeleteRemovedClauses();
213  int64_t num_clauses() const { return clauses_.size(); }
214  const std::vector<SatClause*>& AllClausesInCreationOrder() const {
215  return clauses_;
216  }
217 
218  // True if removing this clause will not change the set of feasible solution.
219  // This is the case for clauses that were learned during search. Note however
220  // that some learned clause are kept forever (heuristics) and do not appear
221  // here.
222  bool IsRemovable(SatClause* const clause) const {
223  return clauses_info_.contains(clause);
224  }
225  int64_t num_removable_clauses() const { return clauses_info_.size(); }
226  absl::flat_hash_map<SatClause*, ClauseInfo>* mutable_clauses_info() {
227  return &clauses_info_;
228  }
229 
230  // Total number of clauses inspected during calls to PropagateOnFalse().
231  int64_t num_inspected_clauses() const { return num_inspected_clauses_; }
233  return num_inspected_clause_literals_;
234  }
235 
236  // The number of different literals (always twice the number of variables).
237  int64_t literal_size() const { return needs_cleaning_.size().value(); }
238 
239  // Number of clauses currently watched.
240  int64_t num_watched_clauses() const { return num_watched_clauses_; }
241 
242  void SetDratProofHandler(DratProofHandler* drat_proof_handler) {
243  drat_proof_handler_ = drat_proof_handler;
244  }
245 
246  // Really basic algorithm to return a clause to try to minimize. We simply
247  // loop over the clause that we keep forever, in creation order. This starts
248  // by the problem clauses and then the learned one that we keep forever.
250  for (; to_minimize_index_ < clauses_.size(); ++to_minimize_index_) {
251  if (!clauses_[to_minimize_index_]->IsAttached()) continue;
252  if (!IsRemovable(clauses_[to_minimize_index_])) {
253  return clauses_[to_minimize_index_++];
254  }
255  }
256  return nullptr;
257  }
258 
259  // Restart the scan in NextClauseToMinimize() from the first problem clause.
260  void ResetToMinimizeIndex() { to_minimize_index_ = 0; }
261 
262  // During an inprocessing phase, it is easier to detach all clause first,
263  // then simplify and then reattach them. Note however that during these
264  // two calls, it is not possible to use the solver unit-progation.
265  //
266  // Important: When reattach is called, we assume that none of their literal
267  // are fixed, so we don't do any special checks.
268  //
269  // These functions can be called multiple-time and do the right things. This
270  // way before doing something, you can call the corresponding function and be
271  // sure to be in a good state. I.e. always AttachAllClauses() before
272  // propagation and DetachAllClauses() before going to do an inprocessing pass
273  // that might transform them.
274  void DetachAllClauses();
275  void AttachAllClauses();
276 
277  // These must only be called between [Detach/Attach]AllClauses() calls.
278  void InprocessingRemoveClause(SatClause* clause);
279  ABSL_MUST_USE_RESULT bool InprocessingFixLiteral(Literal true_literal);
280  ABSL_MUST_USE_RESULT bool InprocessingRewriteClause(
281  SatClause* clause, absl::Span<const Literal> new_clause);
282 
283  // This can return nullptr if new_clause was of size one or two as these are
284  // treated differently. Note that none of the variable should be fixed in the
285  // given new clause.
286  SatClause* InprocessingAddClause(absl::Span<const Literal> new_clause);
287 
288  // Contains, for each literal, the list of clauses that need to be inspected
289  // when the corresponding literal becomes false.
290  struct Watcher {
291  Watcher() {}
292  Watcher(SatClause* c, Literal b, int i = 2)
293  : blocking_literal(b), start_index(i), clause(c) {}
294 
295  // Optimization. A literal from the clause that sometimes allow to not even
296  // look at the clause memory when true.
298 
299  // Optimization. An index in the clause. Instead of looking for another
300  // literal to watch from the start, we will start from here instead, and
301  // loop around if needed. This allows to avoid bad quadratric corner cases
302  // and lead to an "optimal" complexity. See "Optimal Implementation of
303  // Watched Literals and more General Techniques", Ian P. Gent.
304  //
305  // Note that ideally, this should be part of a SatClause, so it can be
306  // shared across watchers. However, since we have 32 bits for "free" here
307  // because of the struct alignment, we store it here instead.
308  int32_t start_index;
309 
311  };
312 
313  // This is exposed since some inprocessing code can heuristically exploit the
314  // currently watched literal and blocking literal to do some simplification.
315  const std::vector<Watcher>& WatcherListOnFalse(Literal false_literal) const {
316  return watchers_on_false_[false_literal.Index()];
317  }
318 
319  private:
320  // Attaches the given clause. This eventually propagates a literal which is
321  // enqueued on the trail. Returns false if a contradiction was encountered.
322  bool AttachAndPropagate(SatClause* clause, Trail* trail);
323 
324  // Launches all propagation when the given literal becomes false.
325  // Returns false if a contradiction was encountered.
326  bool PropagateOnFalse(Literal false_literal, Trail* trail);
327 
328  // Attaches the given clause to the event: the given literal becomes false.
329  // The blocking_literal can be any literal from the clause, it is used to
330  // speed up PropagateOnFalse() by skipping the clause if it is true.
331  void AttachOnFalse(Literal literal, Literal blocking_literal,
332  SatClause* clause);
333 
334  // Common code between LazyDetach() and Detach().
335  void InternalDetach(SatClause* clause);
336 
338 
339  // SatClause reasons by trail_index.
340  std::vector<SatClause*> reasons_;
341 
342  // Indicates if the corresponding watchers_on_false_ list need to be
343  // cleaned. The boolean is_clean_ is just used in DCHECKs.
344  SparseBitset<LiteralIndex> needs_cleaning_;
345  bool is_clean_ = true;
346 
347  BinaryImplicationGraph* implication_graph_;
348  Trail* trail_;
349 
350  int64_t num_inspected_clauses_;
351  int64_t num_inspected_clause_literals_;
352  int64_t num_watched_clauses_;
353  mutable StatsGroup stats_;
354 
355  // For DetachAllClauses()/AttachAllClauses().
356  bool all_clauses_are_attached_ = true;
357 
358  // All the clauses currently in memory. This vector has ownership of the
359  // pointers. We currently do not use std::unique_ptr<SatClause> because it
360  // can't be used with some STL algorithms like std::partition.
361  //
362  // Note that the unit clauses and binary clause are not kept here.
363  std::vector<SatClause*> clauses_;
364 
365  int to_minimize_index_ = 0;
366 
367  // Only contains removable clause.
368  absl::flat_hash_map<SatClause*, ClauseInfo> clauses_info_;
369 
370  DratProofHandler* drat_proof_handler_ = nullptr;
371 
372  DISALLOW_COPY_AND_ASSIGN(LiteralWatchers);
373 };
374 
375 // A binary clause. This is used by BinaryClauseManager.
376 struct BinaryClause {
377  BinaryClause(Literal _a, Literal _b) : a(_a), b(_b) {}
378  bool operator==(BinaryClause o) const { return a == o.a && b == o.b; }
379  bool operator!=(BinaryClause o) const { return a != o.a || b != o.b; }
382 };
383 
384 // A simple class to manage a set of binary clauses.
386  public:
388  int NumClauses() const { return set_.size(); }
389 
390  // Adds a new binary clause to the manager and returns true if it wasn't
391  // already present.
392  bool Add(BinaryClause c) {
393  std::pair<int, int> p(c.a.SignedValue(), c.b.SignedValue());
394  if (p.first > p.second) std::swap(p.first, p.second);
395  if (set_.find(p) == set_.end()) {
396  set_.insert(p);
397  newly_added_.push_back(c);
398  return true;
399  }
400  return false;
401  }
402 
403  // Returns the newly added BinaryClause since the last ClearNewlyAdded() call.
404  const std::vector<BinaryClause>& newly_added() const { return newly_added_; }
405  void ClearNewlyAdded() { newly_added_.clear(); }
406 
407  private:
408  absl::flat_hash_set<std::pair<int, int>> set_;
409  std::vector<BinaryClause> newly_added_;
410  DISALLOW_COPY_AND_ASSIGN(BinaryClauseManager);
411 };
412 
413 // Special class to store and propagate clauses of size 2 (i.e. implication).
414 // Such clauses are never deleted. Together, they represent the 2-SAT part of
415 // the problem. Note that 2-SAT satisfiability is a polynomial problem, but
416 // W2SAT (weighted 2-SAT) is NP-complete.
417 //
418 // TODO(user): Most of the note below are done, but we currently only applies
419 // the reduction before the solve. We should consider doing more in-processing.
420 // The code could probably still be improved too.
421 //
422 // Note(user): All the variables in a strongly connected component are
423 // equivalent and can be thus merged as one. This is relatively cheap to compute
424 // from time to time (linear complexity). We will also get contradiction (a <=>
425 // not a) this way. This is done by DetectEquivalences().
426 //
427 // Note(user): An implication (a => not a) implies that a is false. I am not
428 // sure it is worth detecting that because if the solver assign a to true, it
429 // will learn that right away. I don't think we can do it faster.
430 //
431 // Note(user): The implication graph can be pruned. This is called the
432 // transitive reduction of a graph. For instance If a => {b,c} and b => {c},
433 // then there is no need to store a => {c}. The transitive reduction is unique
434 // on an acyclic graph. Computing it will allow for a faster propagation and
435 // memory reduction. It is however not cheap. Maybe simple lazy heuristics to
436 // remove redundant arcs are better. Note that all the learned clauses we add
437 // will never be redundant (but they could introduce cycles). This is done
438 // by ComputeTransitiveReduction().
439 //
440 // Note(user): This class natively support at most one constraints. This is
441 // a way to reduced significantly the memory and size of some 2-SAT instances.
442 // However, it is not fully exploited for pure SAT problems. See
443 // TransformIntoMaxCliques().
444 //
445 // Note(user): Add a preprocessor to remove duplicates in the implication lists.
446 // Note that all the learned clauses we add will never create duplicates.
447 //
448 // References for most of the above and more:
449 // - Brafman RI, "A simplifier for propositional formulas with many binary
450 // clauses", IEEE Trans Syst Man Cybern B Cybern. 2004 Feb;34(1):52-9.
451 // http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.28.4911
452 // - Marijn J. H. Heule, Matti Järvisalo, Armin Biere, "Efficient CNF
453 // Simplification Based on Binary Implication Graphs", Theory and Applications
454 // of Satisfiability Testing - SAT 2011, Lecture Notes in Computer Science
455 // Volume 6695, 2011, pp 201-215
456 // http://www.cs.helsinki.fi/u/mjarvisa/papers/heule-jarvisalo-biere.sat11.pdf
458  public:
460  : SatPropagator("BinaryImplicationGraph"),
461  stats_("BinaryImplicationGraph"),
462  time_limit_(model->GetOrCreate<TimeLimit>()),
463  random_(model->GetOrCreate<ModelRandomGenerator>()),
464  trail_(model->GetOrCreate<Trail>()) {
465  trail_->RegisterPropagator(this);
466  }
467 
470  LOG(INFO) << stats_.StatString();
471  LOG(INFO) << "num_redundant_implications " << num_redundant_implications_;
472  });
473  }
474 
475  // SatPropagator interface.
476  bool Propagate(Trail* trail) final;
477  absl::Span<const Literal> Reason(const Trail& trail,
478  int trail_index) const final;
479 
480  // Resizes the data structure.
481  void Resize(int num_variables);
482 
483  // Returns true if there is no constraints in this class.
484  bool IsEmpty() const final {
485  return num_implications_ == 0 && at_most_ones_.empty();
486  }
487 
488  // Adds the binary clause (a OR b), which is the same as (not a => b).
489  // Note that it is also equivalent to (not b => a).
492  return AddBinaryClause(a.Negated(), b);
493  }
494 
495  // Same as AddBinaryClause() but enqueues a possible unit propagation. Note
496  // that if the binary clause propagates, it must do so at the last level, this
497  // is DCHECKed.
498  //
499  // Return false and do nothing if both a and b are currently false.
501 
502  // An at most one constraint of size n is a compact way to encode n * (n - 1)
503  // implications. This must only be called at level zero.
504  //
505  // Returns false if this creates a conflict. Currently this can only happens
506  // if there is duplicate literal already assigned to true in this constraint.
507  //
508  // TODO(user): Our algorithm could generalize easily to at_most_ones + a list
509  // of literals that will be false if one of the literal in the amo is at one.
510  // It is a way to merge common list of implications.
511  ABSL_MUST_USE_RESULT bool AddAtMostOne(absl::Span<const Literal> at_most_one);
512 
513  // Uses the binary implication graph to minimize the given conflict by
514  // removing literals that implies others. The idea is that if a and b are two
515  // literals from the given conflict and a => b (which is the same as not(b) =>
516  // not(a)) then a is redundant and can be removed.
517  //
518  // Note that removing as many literals as possible is too time consuming, so
519  // we use different heuristics/algorithms to do this minimization.
520  // See the binary_minimization_algorithm SAT parameter and the .cc for more
521  // details about the different algorithms.
522  void MinimizeConflictWithReachability(std::vector<Literal>* c);
523  void MinimizeConflictExperimental(const Trail& trail,
524  std::vector<Literal>* c);
525  void MinimizeConflictFirst(const Trail& trail, std::vector<Literal>* c,
528  std::vector<Literal>* c,
529  absl::BitGenRef random);
530 
531  // This must only be called at decision level 0 after all the possible
532  // propagations. It:
533  // - Removes the variable at true from the implications lists.
534  // - Frees the propagation list of the assigned literals.
535  void RemoveFixedVariables();
536 
537  // Returns false if the model is unsat, otherwise detects equivalent variable
538  // (with respect to the implications only) and reorganize the propagation
539  // lists accordingly.
540  //
541  // TODO(user): Completely get rid of such literal instead? it might not be
542  // reasonable code-wise to remap our literals in all of our constraints
543  // though.
544  bool DetectEquivalences(bool log_info = false);
545 
546  // Returns true if DetectEquivalences() has been called and no new binary
547  // clauses have been added since then. When this is true then there is no
548  // cycle in the binary implication graph (modulo the redundant literals that
549  // form a cycle with their representative).
550  bool IsDag() const { return is_dag_; }
551 
552  // One must call DetectEquivalences() first, this is CHECKed.
553  // Returns a list so that if x => y, then x is after y.
554  const std::vector<LiteralIndex>& ReverseTopologicalOrder() const {
555  CHECK(is_dag_);
556  return reverse_topological_order_;
557  }
558 
559  // Returns the list of literal "directly" implied by l. Beware that this can
560  // easily change behind your back if you modify the solver state.
561  const absl::InlinedVector<Literal, 6>& Implications(Literal l) const {
562  return implications_[l.Index()];
563  }
564 
565  // Returns the representative of the equivalence class of l (or l itself if it
566  // is on its own). Note that DetectEquivalences() should have been called to
567  // get any non-trival results.
569  if (l.Index() >= representative_of_.size()) return l;
570  if (representative_of_[l.Index()] == kNoLiteralIndex) return l;
571  return Literal(representative_of_[l.Index()]);
572  }
573 
574  // Prunes the implication graph by calling first DetectEquivalences() to
575  // remove cycle and then by computing the transitive reduction of the
576  // remaining DAG.
577  //
578  // Note that this can be slow (num_literals graph traversals), so we abort
579  // early if we start doing too much work.
580  //
581  // Returns false if the model is detected to be UNSAT (this needs to call
582  // DetectEquivalences() if not already done).
583  bool ComputeTransitiveReduction(bool log_info = false);
584 
585  // Another way of representing an implication graph is a list of maximal "at
586  // most one" constraints, each forming a max-clique in the incompatibility
587  // graph. This representation is useful for having a good linear relaxation.
588  //
589  // This function will transform each of the given constraint into a maximal
590  // one in the underlying implication graph. Constraints that are redundant
591  // after other have been expanded (i.e. included into) will be cleared.
592  // Note that the order of constraints will be conserved.
593  //
594  // Returns false if the model is detected to be UNSAT (this needs to call
595  // DetectEquivalences() if not already done).
596  bool TransformIntoMaxCliques(std::vector<std::vector<Literal>>* at_most_ones,
597  int64_t max_num_explored_nodes = 1e8);
598 
599  // LP clique cut heuristic. Returns a set of "at most one" constraints on the
600  // given literals or their negation that are violated by the current LP
601  // solution. Note that this assumes that
602  // lp_value(lit) = 1 - lp_value(lit.Negated()).
603  //
604  // The literal and lp_values vector are in one to one correspondence. We will
605  // only generate clique with these literals or their negation.
606  //
607  // TODO(user): Refine the heuristic and unit test!
608  const std::vector<std::vector<Literal>>& GenerateAtMostOnesWithLargeWeight(
609  const std::vector<Literal>& literals,
610  const std::vector<double>& lp_values);
611 
612  // Number of literal propagated by this class (including conflicts).
613  int64_t num_propagations() const { return num_propagations_; }
614 
615  // Number of literals inspected by this class during propagation.
616  int64_t num_inspections() const { return num_inspections_; }
617 
618  // MinimizeClause() stats.
619  int64_t num_minimization() const { return num_minimization_; }
620  int64_t num_literals_removed() const { return num_literals_removed_; }
621 
622  // Returns true if this literal is fixed or is equivalent to another literal.
623  // This means that it can just be ignored in most situation.
624  //
625  // Note that the set (and thus number) of redundant literal can only grow over
626  // time. This is because we always use the lowest index as representative of
627  // an equivalent class, so a redundant literal will stay that way.
628  bool IsRedundant(Literal l) const { return is_redundant_[l.Index()]; }
629  int64_t num_redundant_literals() const {
630  CHECK_EQ(num_redundant_literals_ % 2, 0);
631  return num_redundant_literals_;
632  }
633 
634  // Number of implications removed by transitive reduction.
635  int64_t num_redundant_implications() const {
636  return num_redundant_implications_;
637  }
638 
639  // Returns the number of current implications. Note that a => b and not(b) =>
640  // not(a) are counted separately since they appear separately in our
641  // propagation lists. The number of size 2 clauses that represent the same
642  // thing is half this number.
643  int64_t num_implications() const { return num_implications_; }
644  int64_t literal_size() const { return implications_.size(); }
645 
646  // Extract all the binary clauses managed by this class. The Output type must
647  // support an AddBinaryClause(Literal a, Literal b) function.
648  //
649  // Important: This currently does NOT include at most one constraints.
650  //
651  // TODO(user): When extracting to cp_model.proto we could be more efficient
652  // by extracting bool_and constraint with many lhs terms.
653  template <typename Output>
654  void ExtractAllBinaryClauses(Output* out) const {
655  // TODO(user): Ideally we should just never have duplicate clauses in this
656  // class. But it seems we do in some corner cases, so lets not output them
657  // twice.
658  absl::flat_hash_set<std::pair<LiteralIndex, LiteralIndex>>
659  duplicate_detection;
660  for (LiteralIndex i(0); i < implications_.size(); ++i) {
661  const Literal a = Literal(i).Negated();
662  for (const Literal b : implications_[i]) {
663  // Note(user): We almost always have both a => b and not(b) => not(a) in
664  // our implications_ database. Except if ComputeTransitiveReduction()
665  // was aborted early, but in this case, if only one is present, the
666  // other could be removed, so we shouldn't need to output it.
667  if (a < b &&
668  duplicate_detection.insert({a.Index(), b.Index()}).second) {
669  out->AddBinaryClause(a, b);
670  }
671  }
672  }
673  }
674 
675  void SetDratProofHandler(DratProofHandler* drat_proof_handler) {
676  drat_proof_handler_ = drat_proof_handler;
677  }
678 
679  // Changes the reason of the variable at trail index to a binary reason.
680  // Note that the implication "new_reason => trail_[trail_index]" should be
681  // part of the implication graph.
682  void ChangeReason(int trail_index, Literal new_reason) {
683  CHECK(trail_->Assignment().LiteralIsTrue(new_reason));
684  reasons_[trail_index] = new_reason.Negated();
685  trail_->ChangeReason(trail_index, propagator_id_);
686  }
687 
688  // The literals that are "directly" implied when literal is set to true. This
689  // is not a full "reachability". It includes at most ones propagation. The set
690  // of all direct implications is enough to describe the implications graph
691  // completely.
692  //
693  // When doing blocked clause elimination of bounded variable elimination, one
694  // only need to consider this list and not the full reachability.
695  const std::vector<Literal>& DirectImplications(Literal literal);
696 
697  // A proxy for DirectImplications().size(), However we currently do not
698  // maintain it perfectly. It is exact each time DirectImplications() is
699  // called, and we update it in some situation but we don't deal with fixed
700  // variables, at_most ones and duplicates implications for now.
702  return estimated_sizes_[literal.Index()];
703  }
704 
705  // Variable elimination by replacing everything of the form a => var => b by a
706  // => b. We ignore any a => a so the number of new implications is not always
707  // just the product of the two direct implication list of var and not(var).
708  // However, if a => var => a, then a and var are equivalent, so this case will
709  // be removed if one run DetectEquivalences() before this. Similarly, if a =>
710  // var => not(a) then a must be false and this is detected and dealt with by
711  // FindFailedLiteralAroundVar().
712  bool FindFailedLiteralAroundVar(BooleanVariable var, bool* is_unsat);
713  int64_t NumImplicationOnVariableRemoval(BooleanVariable var);
715  BooleanVariable var, std::deque<std::vector<Literal>>* postsolve_clauses);
716  bool IsRemoved(Literal l) const { return is_removed_[l.Index()]; }
717 
718  // TODO(user): consider at most ones.
720 
721  // ExpandAtMostOneWithWeight() will increase this, so a client can put a limit
722  // on this possibly expansive operation.
723  void ResetWorkDone() { work_done_in_mark_descendants_ = 0; }
724  int64_t WorkDone() const { return work_done_in_mark_descendants_; }
725 
726  // Same as ExpandAtMostOne() but try to maximize the weight in the clique.
727  template <bool use_weight = true>
728  std::vector<Literal> ExpandAtMostOneWithWeight(
729  const absl::Span<const Literal> at_most_one,
730  const absl::StrongVector<LiteralIndex, bool>& can_be_included,
731  const absl::StrongVector<LiteralIndex, double>& expanded_lp_values);
732 
733  private:
734  // Simple wrapper to not forget to output newly fixed variable to the DRAT
735  // proof if needed. This will propagate rigth away the implications.
736  bool FixLiteral(Literal true_literal);
737 
738  // Propagates all the direct implications of the given literal becoming true.
739  // Returns false if a conflict was encountered, in which case
740  // trail->SetFailingClause() will be called with the correct size 2 clause.
741  // This calls trail->Enqueue() on the newly assigned literals.
742  bool PropagateOnTrue(Literal true_literal, Trail* trail);
743 
744  // Remove any literal whose negation is marked (except the first one).
745  void RemoveRedundantLiterals(std::vector<Literal>* conflict);
746 
747  // Fill is_marked_ with all the descendant of root.
748  // Note that this also use bfs_stack_.
749  void MarkDescendants(Literal root);
750 
751  // Expands greedily the given at most one until we get a maximum clique in
752  // the underlying incompatibility graph. Note that there is no guarantee that
753  // if this is called with any sub-clique of the result we will get the same
754  // maximal clique.
755  std::vector<Literal> ExpandAtMostOne(
756  const absl::Span<const Literal> at_most_one,
757  int64_t max_num_explored_nodes);
758 
759  // Process all at most one constraints starting at or after base_index in
760  // at_most_one_buffer_. This replace literal by their representative, remove
761  // fixed literals and deal with duplicates. Return false iff the model is
762  // UNSAT.
763  bool CleanUpAndAddAtMostOnes(const int base_index);
764 
765  mutable StatsGroup stats_;
766  TimeLimit* time_limit_;
767  ModelRandomGenerator* random_;
768  Trail* trail_;
769  DratProofHandler* drat_proof_handler_ = nullptr;
770 
771  // Binary reasons by trail_index. We need a deque because we kept pointers to
772  // elements of this array and this can dynamically change size.
773  std::deque<Literal> reasons_;
774 
775  // This is indexed by the Index() of a literal. Each list stores the
776  // literals that are implied if the index literal becomes true.
777  //
778  // Using InlinedVector helps quite a bit because on many problems, a literal
779  // only implies a few others. Note that on a 64 bits computer we get exactly
780  // 6 inlined int32_t elements without extra space, and the size of the inlined
781  // vector is 4 times 64 bits.
782  //
783  // TODO(user): We could be even more efficient since a size of int32_t is
784  // enough for us and we could store in common the inlined/not-inlined size.
786  implications_;
787  int64_t num_implications_ = 0;
788 
789  // Internal representation of at_most_one constraints. Each entry point to the
790  // start of a constraint in the buffer. Constraints are terminated by
791  // kNoLiteral. When LiteralIndex is true, then all entry in the at most one
792  // constraint must be false except the one referring to LiteralIndex.
793  //
794  // TODO(user): We could be more cache efficient by combining this with
795  // implications_ in some way. Do some propagation speed benchmark.
797  at_most_ones_;
798  std::vector<Literal> at_most_one_buffer_;
799 
800  // Used by GenerateAtMostOnesWithLargeWeight().
801  std::vector<std::vector<Literal>> tmp_cuts_;
802 
803  // Some stats.
804  int64_t num_propagations_ = 0;
805  int64_t num_inspections_ = 0;
806  int64_t num_minimization_ = 0;
807  int64_t num_literals_removed_ = 0;
808  int64_t num_redundant_implications_ = 0;
809  int64_t num_redundant_literals_ = 0;
810 
811  // Bitset used by MinimizeClause().
812  // TODO(user): use the same one as the one used in the classic minimization
813  // because they are already initialized. Moreover they contains more
814  // information.
815  SparseBitset<LiteralIndex> is_marked_;
816  SparseBitset<LiteralIndex> is_simplified_;
817 
818  // Temporary stack used by MinimizeClauseWithReachability().
819  std::vector<Literal> dfs_stack_;
820 
821  // Used to limit the work done by ComputeTransitiveReduction() and
822  // TransformIntoMaxCliques().
823  int64_t work_done_in_mark_descendants_ = 0;
824  std::vector<Literal> bfs_stack_;
825 
826  // Filled by DetectEquivalences().
827  bool is_dag_ = false;
828  std::vector<LiteralIndex> reverse_topological_order_;
829  Bitset64<LiteralIndex> is_redundant_;
831 
832  // For in-processing and removing variables.
833  std::vector<Literal> direct_implications_;
834  std::vector<Literal> direct_implications_of_negated_literal_;
835  absl::StrongVector<LiteralIndex, bool> in_direct_implications_;
837  absl::StrongVector<LiteralIndex, int> estimated_sizes_;
838 
839  // For RemoveFixedVariables().
840  int num_processed_fixed_variables_ = 0;
841 
842  DISALLOW_COPY_AND_ASSIGN(BinaryImplicationGraph);
843 };
844 
845 extern template std::vector<Literal>
846 BinaryImplicationGraph::ExpandAtMostOneWithWeight<true>(
847  const absl::Span<const Literal> at_most_one,
848  const absl::StrongVector<LiteralIndex, bool>& can_be_included,
849  const absl::StrongVector<LiteralIndex, double>& expanded_lp_values);
850 
851 extern template std::vector<Literal>
852 BinaryImplicationGraph::ExpandAtMostOneWithWeight<false>(
853  const absl::Span<const Literal> at_most_one,
854  const absl::StrongVector<LiteralIndex, bool>& can_be_included,
855  const absl::StrongVector<LiteralIndex, double>& expanded_lp_values);
856 
857 } // namespace sat
858 } // namespace operations_research
859 
860 #endif // OR_TOOLS_SAT_CLAUSE_H_
size_type size() const
bool empty() const
IntegerType size() const
Definition: bitset.h:758
std::string StatString() const
Definition: stats.cc:77
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
Definition: time_limit.h:106
const std::vector< BinaryClause > & newly_added() const
Definition: clause.h:404
const std::vector< LiteralIndex > & ReverseTopologicalOrder() const
Definition: clause.h:554
int64_t NumImplicationOnVariableRemoval(BooleanVariable var)
Definition: clause.cc:2017
void AddBinaryClause(Literal a, Literal b)
Definition: clause.cc:509
bool ComputeTransitiveReduction(bool log_info=false)
Definition: clause.cc:1363
void MinimizeConflictWithReachability(std::vector< Literal > *c)
Definition: clause.cc:804
void ChangeReason(int trail_index, Literal new_reason)
Definition: clause.h:682
bool AddBinaryClauseDuringSearch(Literal a, Literal b)
Definition: clause.cc:526
void MinimizeConflictFirstWithTransitiveReduction(const Trail &trail, std::vector< Literal > *c, absl::BitGenRef random)
Definition: clause.cc:899
const std::vector< std::vector< Literal > > & GenerateAtMostOnesWithLargeWeight(const std::vector< Literal > &literals, const std::vector< double > &lp_values)
Definition: clause.cc:1778
void ExtractAllBinaryClauses(Output *out) const
Definition: clause.h:654
absl::Span< const Literal > Reason(const Trail &trail, int trail_index) const final
Definition: clause.cc:792
Literal RepresentativeOf(Literal l) const
Definition: clause.h:568
void SetDratProofHandler(DratProofHandler *drat_proof_handler)
Definition: clause.h:675
const std::vector< Literal > & DirectImplications(Literal literal)
Definition: clause.cc:1949
void AddImplication(Literal a, Literal b)
Definition: clause.h:491
void MinimizeConflictFirst(const Trail &trail, std::vector< Literal > *c, SparseBitset< BooleanVariable > *marked)
Definition: clause.cc:881
bool DetectEquivalences(bool log_info=false)
Definition: clause.cc:1176
void RemoveBooleanVariable(BooleanVariable var, std::deque< std::vector< Literal >> *postsolve_clauses)
Definition: clause.cc:2037
bool FindFailedLiteralAroundVar(BooleanVariable var, bool *is_unsat)
Definition: clause.cc:1992
const absl::InlinedVector< Literal, 6 > & Implications(Literal l) const
Definition: clause.h:561
bool TransformIntoMaxCliques(std::vector< std::vector< Literal >> *at_most_ones, int64_t max_num_explored_nodes=1e8)
Definition: clause.cc:1542
std::vector< Literal > ExpandAtMostOneWithWeight(const absl::Span< const Literal > at_most_one, const absl::StrongVector< LiteralIndex, bool > &can_be_included, const absl::StrongVector< LiteralIndex, double > &expanded_lp_values)
Definition: clause.cc:1688
ABSL_MUST_USE_RESULT bool AddAtMostOne(absl::Span< const Literal > at_most_one)
Definition: clause.cc:553
void MinimizeConflictExperimental(const Trail &trail, std::vector< Literal > *c)
Definition: clause.cc:961
int DirectImplicationsEstimatedSize(Literal literal) const
Definition: clause.h:701
LiteralIndex Index() const
Definition: sat_base.h:90
const std::vector< SatClause * > & AllClausesInCreationOrder() const
Definition: clause.h:214
ABSL_MUST_USE_RESULT bool InprocessingFixLiteral(Literal true_literal)
Definition: clause.cc:357
absl::flat_hash_map< SatClause *, ClauseInfo > * mutable_clauses_info()
Definition: clause.h:226
bool Propagate(Trail *trail) final
Definition: clause.cc:201
void InprocessingRemoveClause(SatClause *clause)
Definition: clause.cc:376
absl::Span< const Literal > Reason(const Trail &trail, int trail_index) const final
Definition: clause.cc:210
SatClause * AddRemovableClause(const std::vector< Literal > &literals, Trail *trail)
Definition: clause.cc:230
SatClause * InprocessingAddClause(absl::Span< const Literal > new_clause)
Definition: clause.cc:433
void SetDratProofHandler(DratProofHandler *drat_proof_handler)
Definition: clause.h:242
const std::vector< Watcher > & WatcherListOnFalse(Literal false_literal) const
Definition: clause.h:315
void Attach(SatClause *clause, Trail *trail)
Definition: clause.cc:292
bool AddClause(absl::Span< const Literal > literals, Trail *trail)
Definition: clause.cc:223
SatClause * ReasonClause(int trail_index) const
Definition: clause.cc:215
bool IsRemovable(SatClause *const clause) const
Definition: clause.h:222
ABSL_MUST_USE_RESULT bool InprocessingRewriteClause(SatClause *clause, absl::Span< const Literal > new_clause)
Definition: clause.cc:385
void LazyDetach(SatClause *clause)
Definition: clause.cc:312
int64_t num_inspected_clause_literals() const
Definition: clause.h:232
void Detach(SatClause *clause)
Definition: clause.cc:319
void Resize(int num_variables)
Definition: clause.cc:87
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:42
absl::Span< const Literal > AsSpan() const
Definition: clause.h:93
const Literal *const end() const
Definition: clause.h:73
Literal SecondLiteral() const
Definition: clause.h:78
absl::Span< const Literal > PropagationReason() const
Definition: clause.h:88
Literal PropagatedLiteral() const
Definition: clause.h:83
bool IsSatisfied(const VariablesAssignment &assignment) const
Definition: clause.cc:2134
bool RemoveFixedLiteralsAndTestIfTrue(const VariablesAssignment &assignment)
Definition: clause.cc:2110
std::string DebugString() const
Definition: clause.cc:2141
Literal FirstLiteral() const
Definition: clause.h:77
static SatClause * Create(absl::Span< const Literal > literals)
Definition: clause.cc:2097
const Literal *const begin() const
Definition: clause.h:72
void RegisterPropagator(SatPropagator *propagator)
Definition: sat_base.h:587
void ChangeReason(int trail_index, int propagator_id)
Definition: sat_base.h:347
const VariablesAssignment & Assignment() const
Definition: sat_base.h:402
bool LiteralIsTrue(Literal literal) const
Definition: sat_base.h:164
int64_t b
int64_t a
IntVar * var
Definition: expr_array.cc:1874
GRBmodel * model
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:29
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
Definition: id_map.h:269
const LiteralIndex kNoLiteralIndex(-1)
Collection of objects used to extend the Constraint Solver library.
Literal literal
Definition: optimization.cc:88
#define IF_STATS_ENABLED(instructions)
Definition: stats.h:438
bool operator==(BinaryClause o) const
Definition: clause.h:378
bool operator!=(BinaryClause o) const
Definition: clause.h:379
BinaryClause(Literal _a, Literal _b)
Definition: clause.h:377
Watcher(SatClause *c, Literal b, int i=2)
Definition: clause.h:292