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