OR-Tools  9.1
drat_checker.cc
Go to the documentation of this file.
1 // Copyright 2010-2021 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 
15 
16 #include <algorithm>
17 #include <cstdint>
18 #include <fstream>
19 
20 #include "absl/strings/numbers.h"
21 #include "absl/strings/str_split.h"
22 #include "absl/time/clock.h"
23 #include "ortools/base/hash.h"
24 #include "ortools/base/stl_util.h"
26 
27 namespace operations_research {
28 namespace sat {
29 
30 DratChecker::Clause::Clause(int first_literal_index, int num_literals)
31  : first_literal_index(first_literal_index), num_literals(num_literals) {}
32 
33 std::size_t DratChecker::ClauseHash::operator()(
34  const ClauseIndex clause_index) const {
35  size_t hash = 0;
36  for (Literal literal : checker->Literals(checker->clauses_[clause_index])) {
37  hash = util_hash::Hash(literal.Index().value(), hash);
38  }
39  return hash;
40 }
41 
42 bool DratChecker::ClauseEquiv::operator()(
43  const ClauseIndex clause_index1, const ClauseIndex clause_index2) const {
44  return checker->Literals(checker->clauses_[clause_index1]) ==
45  checker->Literals(checker->clauses_[clause_index2]);
46 }
47 
49  : first_infered_clause_index_(kNoClauseIndex),
50  clause_set_(0, ClauseHash(this), ClauseEquiv(this)),
51  num_variables_(0) {}
52 
53 bool DratChecker::Clause::IsDeleted(ClauseIndex clause_index) const {
54  return deleted_index <= clause_index;
55 }
56 
57 void DratChecker::AddProblemClause(absl::Span<const Literal> clause) {
58  DCHECK_EQ(first_infered_clause_index_, kNoClauseIndex);
59  const ClauseIndex clause_index = AddClause(clause);
60 
61  const auto it = clause_set_.find(clause_index);
62  if (it != clause_set_.end()) {
63  clauses_[*it].num_copies += 1;
64  RemoveLastClause();
65  } else {
66  clause_set_.insert(clause_index);
67  }
68 }
69 
70 void DratChecker::AddInferedClause(absl::Span<const Literal> clause) {
71  const ClauseIndex infered_clause_index = AddClause(clause);
72  if (first_infered_clause_index_ == kNoClauseIndex) {
73  first_infered_clause_index_ = infered_clause_index;
74  }
75 
76  const auto it = clause_set_.find(infered_clause_index);
77  if (it != clause_set_.end()) {
78  clauses_[*it].num_copies += 1;
79  if (*it >= first_infered_clause_index_ && !clause.empty()) {
80  CHECK_EQ(clauses_[*it].rat_literal_index, clause[0].Index());
81  }
82  RemoveLastClause();
83  } else {
84  clauses_[infered_clause_index].rat_literal_index =
85  clause.empty() ? kNoLiteralIndex : clause[0].Index();
86  clause_set_.insert(infered_clause_index);
87  }
88 }
89 
90 ClauseIndex DratChecker::AddClause(absl::Span<const Literal> clause) {
91  const int first_literal_index = literals_.size();
92  literals_.insert(literals_.end(), clause.begin(), clause.end());
93  // Sort the input clause in strictly increasing order (by sorting and then
94  // removing the duplicate literals).
95  std::sort(literals_.begin() + first_literal_index, literals_.end());
96  literals_.erase(
97  std::unique(literals_.begin() + first_literal_index, literals_.end()),
98  literals_.end());
99 
100  for (int i = first_literal_index + 1; i < literals_.size(); ++i) {
101  CHECK(literals_[i] != literals_[i - 1].Negated());
102  }
103  clauses_.push_back(
104  Clause(first_literal_index, literals_.size() - first_literal_index));
105  if (!clause.empty()) {
106  num_variables_ =
107  std::max(num_variables_, literals_.back().Variable().value() + 1);
108  }
109  return ClauseIndex(clauses_.size() - 1);
110 }
111 
112 void DratChecker::DeleteClause(absl::Span<const Literal> clause) {
113  // Temporarily add 'clause' to find if it has been previously added.
114  const auto it = clause_set_.find(AddClause(clause));
115  if (it != clause_set_.end()) {
116  Clause& existing_clause = clauses_[*it];
117  existing_clause.num_copies -= 1;
118  if (existing_clause.num_copies == 0) {
119  DCHECK(existing_clause.deleted_index == std::numeric_limits<int>::max());
120  existing_clause.deleted_index = clauses_.size() - 1;
121  if (clauses_.back().num_literals >= 2) {
122  clauses_[ClauseIndex(clauses_.size() - 2)].deleted_clauses.push_back(
123  *it);
124  }
125  clause_set_.erase(it);
126  }
127  } else {
128  LOG(WARNING) << "Couldn't find deleted clause";
129  }
130  // Delete 'clause' and its literals.
131  RemoveLastClause();
132 }
133 
134 void DratChecker::RemoveLastClause() {
135  literals_.resize(clauses_.back().first_literal_index);
136  clauses_.pop_back();
137 }
138 
139 // See Algorithm of Fig. 8 in 'Trimming while Checking Clausal Proofs'.
140 DratChecker::Status DratChecker::Check(double max_time_in_seconds) {
141  // First check that the last infered clause is empty (this implies there
142  // should be at least one infered clause), and mark it as needed for the
143  // proof.
144  if (clauses_.empty() || first_infered_clause_index_ == kNoClauseIndex ||
145  clauses_.back().num_literals != 0) {
146  return Status::INVALID;
147  }
148  clauses_.back().is_needed_for_proof = true;
149 
150  // Checks the infered clauses in reversed order. The advantage of this order
151  // is that when checking a clause, one can mark all the clauses that are used
152  // to check it. In turn, only these marked clauses need to be checked (and so
153  // on recursively). By contrast, a forward iteration needs to check all the
154  // clauses.
155  const int64_t start_time_nanos = absl::GetCurrentTimeNanos();
156  TimeLimit time_limit(max_time_in_seconds);
157  Init();
158  for (ClauseIndex i(clauses_.size() - 1); i >= first_infered_clause_index_;
159  --i) {
160  if (time_limit.LimitReached()) {
161  return Status::UNKNOWN;
162  }
163  const Clause& clause = clauses_[i];
164  // Start watching the literals of the clauses that were deleted just after
165  // this one, and which are now no longer deleted.
166  for (const ClauseIndex j : clause.deleted_clauses) {
167  WatchClause(j);
168  }
169  if (!clause.is_needed_for_proof) {
170  continue;
171  }
172  // 'clause' must have either the Reverse Unit Propagation (RUP) property:
173  if (HasRupProperty(i, Literals(clause))) {
174  continue;
175  }
176  // or the Reverse Asymetric Tautology (RAT) property. This property is
177  // defined by the fact that all clauses which contain the negation of
178  // the RAT literal of 'clause', after resolution with 'clause', must have
179  // the RUP property.
180  // Note from 'DRAT-trim: Efficient Checking and Trimming Using Expressive
181  // Clausal Proofs': "[in order] to access to all clauses containing the
182  // negation of the resolution literal, one could build a literal-to-clause
183  // lookup table of the original formula and update it after each lemma
184  // addition and deletion step. However, these updates can be expensive and
185  // the lookup table potentially doubles the memory usage of the tool.
186  // Since most lemmas emitted by state-of-the-art SAT solvers can be
187  // validated using the RUP check, such a lookup table has been omitted."
188  if (clause.rat_literal_index == kNoLiteralIndex) return Status::INVALID;
189  ++num_rat_checks_;
190  std::vector<Literal> resolvent;
191  for (ClauseIndex j(0); j < i; ++j) {
192  if (!clauses_[j].IsDeleted(i) &&
193  ContainsLiteral(Literals(clauses_[j]),
194  Literal(clause.rat_literal_index).Negated())) {
195  // Check that the resolvent has the RUP property.
196  if (!Resolve(Literals(clause), Literals(clauses_[j]),
197  Literal(clause.rat_literal_index), &tmp_assignment_,
198  &resolvent) ||
199  !HasRupProperty(i, resolvent)) {
200  return Status::INVALID;
201  }
202  }
203  }
204  }
205  LogStatistics(absl::GetCurrentTimeNanos() - start_time_nanos);
206  return Status::VALID;
207 }
208 
209 std::vector<std::vector<Literal>> DratChecker::GetUnsatSubProblem() const {
210  return GetClausesNeededForProof(ClauseIndex(0), first_infered_clause_index_);
211 }
212 
213 std::vector<std::vector<Literal>> DratChecker::GetOptimizedProof() const {
214  return GetClausesNeededForProof(first_infered_clause_index_,
215  ClauseIndex(clauses_.size()));
216 }
217 
218 std::vector<std::vector<Literal>> DratChecker::GetClausesNeededForProof(
219  ClauseIndex begin, ClauseIndex end) const {
220  std::vector<std::vector<Literal>> result;
221  for (ClauseIndex i = begin; i < end; ++i) {
222  const Clause& clause = clauses_[i];
223  if (clause.is_needed_for_proof) {
224  const absl::Span<const Literal>& literals = Literals(clause);
225  result.emplace_back(literals.begin(), literals.end());
226  if (clause.rat_literal_index != kNoLiteralIndex) {
227  const int rat_literal_clause_index =
228  std::find(literals.begin(), literals.end(),
229  Literal(clause.rat_literal_index)) -
230  literals.begin();
231  std::swap(result.back()[0], result.back()[rat_literal_clause_index]);
232  }
233  }
234  }
235  return result;
236 }
237 
238 absl::Span<const Literal> DratChecker::Literals(const Clause& clause) const {
239  return absl::Span<const Literal>(
240  literals_.data() + clause.first_literal_index, clause.num_literals);
241 }
242 
243 void DratChecker::Init() {
244  assigned_.clear();
245  assignment_.Resize(num_variables_);
246  assignment_source_.resize(num_variables_, kNoClauseIndex);
247  high_priority_literals_to_assign_.clear();
248  low_priority_literals_to_assign_.clear();
249  watched_literals_.clear();
250  watched_literals_.resize(2 * num_variables_);
251  single_literal_clauses_.clear();
252  unit_stack_.clear();
253  tmp_assignment_.Resize(num_variables_);
254  num_rat_checks_ = 0;
255 
256  for (ClauseIndex clause_index(0); clause_index < clauses_.size();
257  ++clause_index) {
258  Clause& clause = clauses_[clause_index];
259  if (clause.num_literals >= 2) {
260  // Don't watch the literals of the deleted clauses right away, instead
261  // watch them when these clauses become 'undeleted' in backward checking.
262  if (clause.deleted_index == std::numeric_limits<int>::max()) {
263  WatchClause(clause_index);
264  }
265  } else if (clause.num_literals == 1) {
266  single_literal_clauses_.push_back(clause_index);
267  }
268  }
269 }
270 
271 void DratChecker::WatchClause(ClauseIndex clause_index) {
272  const Literal* clause_literals =
273  literals_.data() + clauses_[clause_index].first_literal_index;
274  watched_literals_[clause_literals[0].Index()].push_back(clause_index);
275  watched_literals_[clause_literals[1].Index()].push_back(clause_index);
276 }
277 
278 bool DratChecker::HasRupProperty(ClauseIndex num_clauses,
279  absl::Span<const Literal> clause) {
280  ClauseIndex conflict = kNoClauseIndex;
281  for (const Literal literal : clause) {
282  conflict =
283  AssignAndPropagate(num_clauses, literal.Negated(), kNoClauseIndex);
284  if (conflict != kNoClauseIndex) {
285  break;
286  }
287  }
288 
289  for (const ClauseIndex clause_index : single_literal_clauses_) {
290  const Clause& clause = clauses_[clause_index];
291  // TODO(user): consider ignoring the deletion of single literal clauses
292  // as done in drat-trim.
293  if (clause_index < num_clauses && !clause.IsDeleted(num_clauses)) {
294  if (clause.is_needed_for_proof) {
295  high_priority_literals_to_assign_.push_back(
296  {literals_[clause.first_literal_index], clause_index});
297  } else {
298  low_priority_literals_to_assign_.push_back(
299  {literals_[clause.first_literal_index], clause_index});
300  }
301  }
302  }
303 
304  while (!(high_priority_literals_to_assign_.empty() &&
305  low_priority_literals_to_assign_.empty()) &&
306  conflict == kNoClauseIndex) {
307  std::vector<LiteralToAssign>& stack =
308  high_priority_literals_to_assign_.empty()
309  ? low_priority_literals_to_assign_
310  : high_priority_literals_to_assign_;
311  const LiteralToAssign literal_to_assign = stack.back();
312  stack.pop_back();
313  if (assignment_.LiteralIsAssigned(literal_to_assign.literal)) {
314  // If the literal to assign to true is already assigned to false, we found
315  // a conflict, with the source clause of this previous assignment.
316  if (assignment_.LiteralIsFalse(literal_to_assign.literal)) {
317  conflict = literal_to_assign.source_clause_index;
318  break;
319  } else {
320  continue;
321  }
322  }
323  DCHECK(literal_to_assign.source_clause_index != kNoClauseIndex);
324  unit_stack_.push_back(literal_to_assign.source_clause_index);
325  conflict = AssignAndPropagate(num_clauses, literal_to_assign.literal,
326  literal_to_assign.source_clause_index);
327  }
328  if (conflict != kNoClauseIndex) {
329  MarkAsNeededForProof(&clauses_[conflict]);
330  }
331 
332  for (const Literal literal : assigned_) {
333  assignment_.UnassignLiteral(literal);
334  }
335  assigned_.clear();
336  high_priority_literals_to_assign_.clear();
337  low_priority_literals_to_assign_.clear();
338  unit_stack_.clear();
339 
340  return conflict != kNoClauseIndex;
341 }
342 
343 ClauseIndex DratChecker::AssignAndPropagate(ClauseIndex num_clauses,
344  Literal literal,
345  ClauseIndex source_clause_index) {
346  assigned_.push_back(literal);
347  assignment_.AssignFromTrueLiteral(literal);
348  assignment_source_[literal.Variable()] = source_clause_index;
349 
350  const Literal false_literal = literal.Negated();
351  std::vector<ClauseIndex>& watched = watched_literals_[false_literal.Index()];
352  int new_watched_size = 0;
353  ClauseIndex conflict_index = kNoClauseIndex;
354  for (const ClauseIndex clause_index : watched) {
355  if (clause_index >= num_clauses) {
356  // Stop watching the literals of clauses which cannot possibly be
357  // necessary to check the rest of the proof.
358  continue;
359  }
360  Clause& clause = clauses_[clause_index];
361  DCHECK(!clause.IsDeleted(num_clauses));
362  if (conflict_index != kNoClauseIndex) {
363  watched[new_watched_size++] = clause_index;
364  continue;
365  }
366 
367  Literal* clause_literals = literals_.data() + clause.first_literal_index;
368  const Literal other_watched_literal(LiteralIndex(
369  clause_literals[0].Index().value() ^
370  clause_literals[1].Index().value() ^ false_literal.Index().value()));
371  if (assignment_.LiteralIsTrue(other_watched_literal)) {
372  watched[new_watched_size++] = clause_index;
373  continue;
374  }
375 
376  bool new_watched_literal_found = false;
377  for (int i = 2; i < clause.num_literals; ++i) {
378  if (!assignment_.LiteralIsFalse(clause_literals[i])) {
379  clause_literals[0] = other_watched_literal;
380  clause_literals[1] = clause_literals[i];
381  clause_literals[i] = false_literal;
382  watched_literals_[clause_literals[1].Index()].push_back(clause_index);
383  new_watched_literal_found = true;
384  break;
385  }
386  }
387 
388  if (!new_watched_literal_found) {
389  if (assignment_.LiteralIsFalse(other_watched_literal)) {
390  // 'clause' is falsified with 'assignment_', we found a conflict.
391  // TODO(user): test moving the rest of the vector here and
392  // returning right away.
393  conflict_index = clause_index;
394  } else {
395  DCHECK(!assignment_.LiteralIsAssigned(other_watched_literal));
396  // 'clause' is unit, push its unit literal on
397  // 'literals_to_assign_high_priority' or
398  // 'literals_to_assign_low_priority' to assign it to true and propagate
399  // it in a later call to AssignAndPropagate().
400  if (clause.is_needed_for_proof) {
401  high_priority_literals_to_assign_.push_back(
402  {other_watched_literal, clause_index});
403  } else {
404  low_priority_literals_to_assign_.push_back(
405  {other_watched_literal, clause_index});
406  }
407  }
408  watched[new_watched_size++] = clause_index;
409  }
410  }
411  watched.resize(new_watched_size);
412  return conflict_index;
413 }
414 
415 void DratChecker::MarkAsNeededForProof(Clause* clause) {
416  const auto mark_clause_and_sources = [&](Clause* clause) {
417  clause->is_needed_for_proof = true;
418  for (const Literal literal : Literals(*clause)) {
419  const ClauseIndex source_clause_index =
420  assignment_source_[literal.Variable()];
421  if (source_clause_index != kNoClauseIndex) {
422  clauses_[source_clause_index].tmp_is_needed_for_proof_step = true;
423  }
424  }
425  };
426  mark_clause_and_sources(clause);
427  for (int i = unit_stack_.size() - 1; i >= 0; --i) {
428  Clause& unit_clause = clauses_[unit_stack_[i]];
429  if (unit_clause.tmp_is_needed_for_proof_step) {
430  mark_clause_and_sources(&unit_clause);
431  // We can clean this flag here without risking missing clauses needed for
432  // the proof, because the clauses needed for a clause C are always lower
433  // than C in the stack.
434  unit_clause.tmp_is_needed_for_proof_step = false;
435  }
436  }
437 }
438 
439 void DratChecker::LogStatistics(int64_t duration_nanos) const {
440  int problem_clauses_needed_for_proof = 0;
441  int infered_clauses_needed_for_proof = 0;
442  for (ClauseIndex i(0); i < clauses_.size(); ++i) {
443  if (clauses_[i].is_needed_for_proof) {
444  if (i < first_infered_clause_index_) {
445  ++problem_clauses_needed_for_proof;
446  } else {
447  ++infered_clauses_needed_for_proof;
448  }
449  }
450  }
451  LOG(INFO) << problem_clauses_needed_for_proof
452  << " problem clauses needed for proof, out of "
453  << first_infered_clause_index_;
454  LOG(INFO) << infered_clauses_needed_for_proof
455  << " infered clauses needed for proof, out of "
456  << clauses_.size() - first_infered_clause_index_;
457  LOG(INFO) << num_rat_checks_ << " RAT infered clauses";
458  LOG(INFO) << "verification time: " << 1e-9 * duration_nanos << " s";
459 }
460 
461 bool ContainsLiteral(absl::Span<const Literal> clause, Literal literal) {
462  return std::find(clause.begin(), clause.end(), literal) != clause.end();
463 }
464 
465 bool Resolve(absl::Span<const Literal> clause,
466  absl::Span<const Literal> other_clause,
467  Literal complementary_literal, VariablesAssignment* assignment,
468  std::vector<Literal>* resolvent) {
469  DCHECK(ContainsLiteral(clause, complementary_literal));
470  DCHECK(ContainsLiteral(other_clause, complementary_literal.Negated()));
471  resolvent->clear();
472 
473  for (const Literal literal : clause) {
474  if (literal != complementary_literal) {
475  // Temporary assignment used to do the checks below in linear time.
476  assignment->AssignFromTrueLiteral(literal);
477  resolvent->push_back(literal);
478  }
479  }
480 
481  bool result = true;
482  for (const Literal other_literal : other_clause) {
483  if (other_literal != complementary_literal.Negated()) {
484  if (assignment->LiteralIsFalse(other_literal)) {
485  result = false;
486  break;
487  } else if (!assignment->LiteralIsAssigned(other_literal)) {
488  resolvent->push_back(other_literal);
489  }
490  }
491  }
492 
493  // Revert the temporary assignment done above.
494  for (const Literal literal : clause) {
495  if (literal != complementary_literal) {
496  assignment->UnassignLiteral(literal);
497  }
498  }
499  return result;
500 }
501 
502 bool AddProblemClauses(const std::string& file_path,
503  DratChecker* drat_checker) {
504  int line_number = 0;
505  int num_variables = 0;
506  int num_clauses = 0;
507  std::vector<Literal> literals;
508  std::ifstream file(file_path);
509  std::string line;
510  bool result = true;
511  while (std::getline(file, line)) {
512  line_number++;
513  std::vector<absl::string_view> words =
514  absl::StrSplit(line, absl::ByAnyChar(" \t"), absl::SkipWhitespace());
515  if (words.empty() || words[0] == "c") {
516  // Ignore empty and comment lines.
517  continue;
518  }
519  if (words[0] == "p") {
520  if (num_clauses > 0 || words.size() != 4 || words[1] != "cnf" ||
521  !absl::SimpleAtoi(words[2], &num_variables) || num_variables <= 0 ||
522  !absl::SimpleAtoi(words[3], &num_clauses) || num_clauses <= 0) {
523  LOG(ERROR) << "Invalid content '" << line << "' at line " << line_number
524  << " of " << file_path;
525  result = false;
526  break;
527  }
528  continue;
529  }
530  literals.clear();
531  for (int i = 0; i < words.size(); ++i) {
532  int signed_value;
533  if (!absl::SimpleAtoi(words[i], &signed_value) ||
534  std::abs(signed_value) > num_variables ||
535  (signed_value == 0 && i != words.size() - 1)) {
536  LOG(ERROR) << "Invalid content '" << line << "' at line " << line_number
537  << " of " << file_path;
538  result = false;
539  break;
540  }
541  if (signed_value != 0) {
542  literals.push_back(Literal(signed_value));
543  }
544  }
545  drat_checker->AddProblemClause(literals);
546  }
547  file.close();
548  return result;
549 }
550 
551 bool AddInferedAndDeletedClauses(const std::string& file_path,
552  DratChecker* drat_checker) {
553  int line_number = 0;
554  bool ends_with_empty_clause = false;
555  std::vector<Literal> literals;
556  std::ifstream file(file_path);
557  std::string line;
558  bool result = true;
559  while (std::getline(file, line)) {
560  line_number++;
561  std::vector<absl::string_view> words =
562  absl::StrSplit(line, absl::ByAnyChar(" \t"), absl::SkipWhitespace());
563  bool delete_clause = !words.empty() && words[0] == "d";
564  literals.clear();
565  for (int i = (delete_clause ? 1 : 0); i < words.size(); ++i) {
566  int signed_value;
567  if (!absl::SimpleAtoi(words[i], &signed_value) ||
568  (signed_value == 0 && i != words.size() - 1)) {
569  LOG(ERROR) << "Invalid content '" << line << "' at line " << line_number
570  << " of " << file_path;
571  result = false;
572  break;
573  }
574  if (signed_value != 0) {
575  literals.push_back(Literal(signed_value));
576  }
577  }
578  if (delete_clause) {
579  drat_checker->DeleteClause(literals);
580  ends_with_empty_clause = false;
581  } else {
582  drat_checker->AddInferedClause(literals);
583  ends_with_empty_clause = literals.empty();
584  }
585  }
586  if (!ends_with_empty_clause) {
587  drat_checker->AddInferedClause({});
588  }
589  file.close();
590  return result;
591 }
592 
593 bool PrintClauses(const std::string& file_path, SatFormat format,
594  const std::vector<std::vector<Literal>>& clauses,
595  int num_variables) {
596  std::ofstream output_stream(file_path, std::ofstream::out);
597  if (format == DIMACS) {
598  output_stream << "p cnf " << num_variables << " " << clauses.size() << "\n";
599  }
600  for (const auto& clause : clauses) {
601  for (Literal literal : clause) {
602  output_stream << literal.SignedValue() << " ";
603  }
604  output_stream << "0\n";
605  }
606  output_stream.close();
607  return output_stream.good();
608 }
609 
610 } // namespace sat
611 } // namespace operations_research
uint64_t Hash(uint64_t num, uint64_t c)
Definition: hash.h:150
#define CHECK(condition)
Definition: base/logging.h:491
std::vector< std::vector< Literal > > GetOptimizedProof() const
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
Definition: time_limit.h:105
bool AddInferedAndDeletedClauses(const std::string &file_path, DratChecker *drat_checker)
ModelSharedTimeLimit * time_limit
const int ERROR
Definition: log_severity.h:32
bool LiteralIsFalse(Literal literal) const
Definition: sat_base.h:148
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
Definition: id_map.h:263
bool LiteralIsTrue(Literal literal) const
Definition: sat_base.h:151
void AssignFromTrueLiteral(Literal literal)
Definition: sat_base.h:134
LiteralIndex Index() const
Definition: sat_base.h:85
#define LOG(severity)
Definition: base/logging.h:416
bool ContainsLiteral(absl::Span< const Literal > clause, Literal literal)
bool PrintClauses(const std::string &file_path, SatFormat format, const std::vector< std::vector< Literal >> &clauses, int num_variables)
int64_t max
Definition: alldiff_cst.cc:140
void resize(size_type new_size)
std::vector< std::vector< Literal > > GetUnsatSubProblem() const
void DeleteClause(absl::Span< const Literal > clause)
const int WARNING
Definition: log_severity.h:31
bool empty() const
Status Check(double max_time_in_seconds)
int64_t hash
Definition: matrix_utils.cc:61
bool LiteralIsAssigned(Literal literal) const
Definition: sat_base.h:154
const ClauseIndex kNoClauseIndex(-1)
void push_back(const value_type &x)
void AddProblemClause(absl::Span< const Literal > clause)
Definition: drat_checker.cc:57
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:698
void AddInferedClause(absl::Span< const Literal > clause)
Definition: drat_checker.cc:70
size_type size() const
#define DCHECK(condition)
Definition: base/logging.h:885
#define DCHECK_EQ(val1, val2)
Definition: base/logging.h:886
Collection of objects used to extend the Constraint Solver library.
const LiteralIndex kNoLiteralIndex(-1)
bool AddProblemClauses(const std::string &file_path, DratChecker *drat_checker)
int64_t value
Literal literal
Definition: optimization.cc:85
bool Resolve(absl::Span< const Literal > clause, absl::Span< const Literal > other_clause, Literal complementary_literal, VariablesAssignment *assignment, std::vector< Literal > *resolvent)
const int INFO
Definition: log_severity.h:31