4040#include " ortools/base/timer.h"
4141#include " ortools/graph/strongly_connected_components.h"
4242#include " ortools/sat/container.h"
43- #include " ortools/sat/drat_proof_handler.h"
4443#include " ortools/sat/inclusion.h"
4544#include " ortools/sat/lrat_proof_handler.h"
4645#include " ortools/sat/model.h"
@@ -398,20 +397,15 @@ void ClauseManager::Attach(SatClause* clause, Trail* trail) {
398397
399398void ClauseManager::InternalDetach (SatClause* clause,
400399 DeletionSourceForStat source) {
401- const size_t size = clause->size ();
402-
403400 // Double-deletion.
404401 // TODO(user): change that to a check?
405- if (size == 0 ) return ;
402+ if (clause-> size () == 0 ) return ;
406403
407404 --num_watched_clauses_;
408- if (drat_proof_handler_ != nullptr && size > 2 ) {
409- drat_proof_handler_->DeleteClause ({clause->begin (), size});
410- }
411405 if (lrat_proof_handler_ != nullptr ) {
412406 const auto it = clause_id_.find (clause);
413407 if (it != clause_id_.end ()) {
414- lrat_proof_handler_->DeleteClauses ({ it->second } );
408+ lrat_proof_handler_->DeleteClause ( it->second , clause-> AsSpan () );
415409 clause_id_.erase (it);
416410 }
417411 }
@@ -460,9 +454,6 @@ void ClauseManager::AttachAllClauses() {
460454bool ClauseManager::InprocessingAddUnitClause (ClauseId unit_clause_id,
461455 Literal true_literal) {
462456 DCHECK_EQ (trail_->CurrentDecisionLevel (), 0 );
463- if (drat_proof_handler_ != nullptr ) {
464- drat_proof_handler_->AddClause ({true_literal});
465- }
466457 if (trail_->Assignment ().LiteralIsTrue (true_literal)) return true ;
467458
468459 trail_->EnqueueWithUnitReason (unit_clause_id, true_literal);
@@ -475,9 +466,6 @@ bool ClauseManager::InprocessingAddUnitClause(ClauseId unit_clause_id,
475466bool ClauseManager::InprocessingFixLiteral (
476467 Literal true_literal, absl::Span<const ClauseId> clause_ids) {
477468 DCHECK_EQ (trail_->CurrentDecisionLevel (), 0 );
478- if (drat_proof_handler_ != nullptr ) {
479- drat_proof_handler_->AddClause ({true_literal});
480- }
481469 if (trail_->Assignment ().LiteralIsTrue (true_literal)) return true ;
482470
483471 ClauseId clause_id = kNoClauseId ;
@@ -530,10 +518,12 @@ bool ClauseManager::InprocessingRewriteClause(
530518 return true ;
531519 }
532520
533- if (drat_proof_handler_ != nullptr ) {
534- // We must write the new clause before we delete the old one.
535- drat_proof_handler_->AddClause (new_clause);
536- drat_proof_handler_->DeleteClause (clause->AsSpan ());
521+ if (lrat_proof_handler_ != nullptr ) {
522+ const auto it = clause_id_.find (clause);
523+ if (it != clause_id_.end ()) {
524+ lrat_proof_handler_->DeleteClause (it->second , clause->AsSpan ());
525+ }
526+ SetClauseId (clause, new_clause_id);
537527 }
538528
539529 if (all_clauses_are_attached_) {
@@ -543,25 +533,13 @@ bool ClauseManager::InprocessingRewriteClause(
543533 clause->Clear ();
544534 for (const Literal l : {clause->FirstLiteral (), clause->SecondLiteral ()}) {
545535 needs_cleaning_.Clear (l);
546- // std::erase_if is C++20, not yet fully supported on OR-Tools.
547- watchers_on_false_[l].erase (
548- std::remove_if (watchers_on_false_[l].begin (),
549- watchers_on_false_[l].end (),
550- [](const Watcher& watcher) {
551- return watcher.clause ->IsRemoved ();
552- }),
553- watchers_on_false_[l].end ());
536+ OpenSourceEraseIf (watchers_on_false_[l], [](const Watcher& watcher) {
537+ return watcher.clause ->IsRemoved ();
538+ });
554539 }
555540 }
556541
557542 clause->Rewrite (new_clause);
558- if (lrat_proof_handler_ != nullptr ) {
559- const auto it = clause_id_.find (clause);
560- if (it != clause_id_.end ()) {
561- lrat_proof_handler_->DeleteClauses ({it->second });
562- }
563- SetClauseId (clause, new_clause_id);
564- }
565543
566544 // And we reattach it.
567545 if (all_clauses_are_attached_) {
@@ -601,12 +579,9 @@ void ClauseManager::CleanUpWatchers() {
601579 SCOPED_TIME_STAT (&stats_);
602580 for (const LiteralIndex index : needs_cleaning_.PositionsSetAtLeastOnce ()) {
603581 if (!needs_cleaning_[index]) continue ;
604- // std::erase_if is C++20, not yet fully supported on OR-Tools.
605- watchers_on_false_[index].erase (
606- std::remove_if (
607- watchers_on_false_[index].begin (), watchers_on_false_[index].end (),
608- [](const Watcher& watcher) { return watcher.clause ->IsRemoved (); }),
609- watchers_on_false_[index].end ());
582+ OpenSourceEraseIf (watchers_on_false_[index], [](const Watcher& watcher) {
583+ return watcher.clause ->IsRemoved ();
584+ });
610585 needs_cleaning_.Clear (index);
611586 }
612587 needs_cleaning_.NotifyAllClear ();
@@ -789,24 +764,16 @@ bool BinaryImplicationGraph::HasNoDuplicates() {
789764// use them here to maintains invariant? Explore this when we start cleaning our
790765// clauses using equivalence during search. We can easily do it for every
791766// conflict we learn instead of here.
792- bool BinaryImplicationGraph::AddBinaryClauseInternal (ClauseId id, Literal a,
793- Literal b,
794- bool change_reason ) {
767+ bool BinaryImplicationGraph::AddBinaryClauseInternal (
768+ ClauseId id, Literal a, Literal b, bool change_reason ,
769+ bool delete_non_representative_id ) {
795770 SCOPED_TIME_STAT (&stats_);
796771
797772 // Tricky: If this is the first clause, the propagator will be added and
798773 // assumed to be in a "propagated" state. This makes sure this is the case.
799774 if (no_constraint_ever_added_) propagation_trail_index_ = trail_->Index ();
800775 no_constraint_ever_added_ = false ;
801776
802- if (drat_proof_handler_ != nullptr ) {
803- // TODO(user): Like this we will duplicate all binary clause from the
804- // problem. However this leads to a simpler API (since we don't need to
805- // special case the loading of the original clauses) and we mainly use drat
806- // proof for testing anyway.
807- drat_proof_handler_->AddClause ({a, b});
808- }
809-
810777 Literal rep_a = a;
811778 Literal rep_b = b;
812779 ClauseId rep_id = kNoClauseId ;
@@ -839,8 +806,8 @@ bool BinaryImplicationGraph::AddBinaryClauseInternal(ClauseId id, Literal a,
839806 // Remember the non-canonical clause so we can delete it on restart.
840807 changed_reasons_on_trail_.emplace_back (std::minmax (a, b));
841808 AddClauseId (id, a, b);
842- } else {
843- lrat_proof_handler_->DeleteClauses ({id });
809+ } else if (delete_non_representative_id) {
810+ lrat_proof_handler_->DeleteClause (id, {a, b });
844811 }
845812 }
846813 AddClauseId (rep_id, rep_a, rep_b);
@@ -939,9 +906,6 @@ bool BinaryImplicationGraph::FixLiteral(Literal true_literal,
939906 return false ;
940907 }
941908
942- if (drat_proof_handler_ != nullptr ) {
943- drat_proof_handler_->AddClause ({true_literal});
944- }
945909 ClauseId new_clause_id = kNoClauseId ;
946910 if (lrat_proof_handler_ != nullptr ) {
947911 new_clause_id = clause_id_generator_->GetNextId ();
@@ -1515,7 +1479,6 @@ class LratEquivalenceHelper {
15151479 trail_(graph->trail_),
15161480 implications_and_amos_(graph->implications_and_amos_),
15171481 clause_id_generator_(graph->clause_id_generator_),
1518- drat_proof_handler_(graph->drat_proof_handler_),
15191482 lrat_proof_handler_(graph->lrat_proof_handler_) {}
15201483
15211484 // Initializes the internal data structures to process the given component
@@ -1714,9 +1677,6 @@ class LratEquivalenceHelper {
17141677 void AddInferredClause (ClauseId new_clause_id,
17151678 absl::Span<const Literal> literals,
17161679 absl::Span<const ClauseId> clause_ids) {
1717- if (drat_proof_handler_ != nullptr ) {
1718- drat_proof_handler_->AddClause (literals);
1719- }
17201680 if (lrat_proof_handler_ != nullptr ) {
17211681 lrat_proof_handler_->AddInferredClause (new_clause_id, literals,
17221682 clause_ids);
@@ -1728,7 +1688,6 @@ class LratEquivalenceHelper {
17281688 util_intops::StrongVector<LiteralIndex, LiteralsOrOffsets>&
17291689 implications_and_amos_;
17301690 ClauseIdGenerator* clause_id_generator_;
1731- DratProofHandler* drat_proof_handler_;
17321691 LratProofHandler* lrat_proof_handler_;
17331692
17341693 // Temporary data structures used by the above methods:
@@ -1745,14 +1704,6 @@ class LratEquivalenceHelper {
17451704 std::vector<Literal> tmp_literals_;
17461705};
17471706
1748- void BinaryImplicationGraph::SetDratProofHandler (
1749- DratProofHandler* drat_proof_handler) {
1750- drat_proof_handler_ = drat_proof_handler;
1751- if (lrat_helper_ == nullptr ) {
1752- lrat_helper_ = new LratEquivalenceHelper (this );
1753- }
1754- }
1755-
17561707bool BinaryImplicationGraph::DetectEquivalences (bool log_info) {
17571708 // This was already called, and no new constraint where added. Note that new
17581709 // fixed variable cannot create new equivalence, only new binary clauses do.
@@ -1764,7 +1715,8 @@ bool BinaryImplicationGraph::DetectEquivalences(bool log_info) {
17641715 if (trail_->CurrentDecisionLevel () == 0 ) {
17651716 for (std::pair<Literal, Literal> clause : changed_reasons_on_trail_) {
17661717 auto it = clause_id_.find (clause);
1767- lrat_proof_handler_->DeleteClauses ({it->second });
1718+ lrat_proof_handler_->DeleteClause (it->second ,
1719+ {clause.first , clause.second });
17681720 clause_id_.erase (it);
17691721 }
17701722 changed_reasons_on_trail_.clear ();
@@ -3157,15 +3109,9 @@ void BinaryImplicationGraph::RemoveBooleanVariable(
31573109 // Notify the deletion to the proof checker and the postsolve.
31583110 // Note that we want var first in these clauses for the postsolve.
31593111 for (const Literal b : direct_implications_) {
3160- if (drat_proof_handler_ != nullptr ) {
3161- drat_proof_handler_->DeleteClause ({Literal (var, false ), b});
3162- }
31633112 postsolve_clauses->push_back ({Literal (var, false ), b});
31643113 }
31653114 for (const Literal a_negated : direct_implications_of_negated_literal_) {
3166- if (drat_proof_handler_ != nullptr ) {
3167- drat_proof_handler_->DeleteClause ({Literal (var, true ), a_negated});
3168- }
31693115 postsolve_clauses->push_back ({Literal (var, true ), a_negated});
31703116 }
31713117
0 commit comments