@@ -244,21 +244,25 @@ bool ClauseManager::Propagate(Trail* trail) {
244244 }
245245 }
246246
247- reasons_[trail->Index ()] = it->clause ;
248- if (propagation_level == 0 && lrat_proof_handler_ != nullptr ) {
249- const ClauseId clause_id = GetClauseId (it->clause );
250- const int size = it->clause ->size ();
251- std::vector<ClauseId>& unit_ids = clause_ids_scratchpad_;
252- unit_ids.clear ();
253- for (int i = 1 ; i < size; ++i) {
254- unit_ids.push_back (trail_->GetUnitClauseId (literals[i].Variable ()));
247+ if (propagation_level == 0 ) {
248+ if (lrat_proof_handler_ != nullptr ) {
249+ std::vector<ClauseId>& unit_ids = clause_ids_scratchpad_;
250+ unit_ids.clear ();
251+ const int size = it->clause ->size ();
252+ for (int i = 1 ; i < size; ++i) {
253+ unit_ids.push_back (
254+ trail_->GetUnitClauseId (literals[i].Variable ()));
255+ }
256+ unit_ids.push_back (GetClauseId (it->clause ));
257+ const ClauseId new_clause_id = clause_id_generator_->GetNextId ();
258+ lrat_proof_handler_->AddInferredClause (
259+ new_clause_id, {other_watched_literal}, unit_ids);
260+ helper.EnqueueWithUnitReason (other_watched_literal, new_clause_id);
261+ } else {
262+ trail_->EnqueueWithUnitReason (other_watched_literal);
255263 }
256- unit_ids.push_back (clause_id);
257- const ClauseId new_clause_id = clause_id_generator_->GetNextId ();
258- lrat_proof_handler_->AddInferredClause (
259- new_clause_id, {other_watched_literal}, unit_ids);
260- helper.EnqueueWithUnitReason (other_watched_literal, new_clause_id);
261264 } else {
265+ reasons_[trail->Index ()] = it->clause ;
262266 helper.EnqueueAtLevel (other_watched_literal, propagation_level);
263267 }
264268 *new_it++ = *it;
@@ -296,6 +300,7 @@ SatClause* ClauseManager::ReasonClauseOrNull(BooleanVariable var) const {
296300 if (!trail_->Assignment ().VariableIsAssigned (var)) return nullptr ;
297301 if (trail_->AssignmentType (var) != propagator_id_) return nullptr ;
298302 SatClause* result = reasons_[trail_->Info (var).trail_index ];
303+ DCHECK (result != nullptr ) << trail_->Info (var).DebugString ();
299304
300305 // Tricky: In some corner case, that clause was subsumed, so we don't want
301306 // to check it nor use it.
@@ -306,6 +311,7 @@ SatClause* ClauseManager::ReasonClauseOrNull(BooleanVariable var) const {
306311
307312bool ClauseManager::ClauseIsUsedAsReason (SatClause* clause) const {
308313 DCHECK (clause != nullptr );
314+ if (clause->empty ()) return false ;
309315 return clause == ReasonClauseOrNull (clause->PropagatedLiteral ().Variable ());
310316}
311317
@@ -642,13 +648,24 @@ void ClauseManager::CleanUpWatchers() {
642648void ClauseManager::DeleteRemovedClauses () {
643649 if (!is_clean_) CleanUpWatchers ();
644650
651+ if (DEBUG_MODE) {
652+ // This help debug issues, as it is easier to check for nullptr rather than
653+ // detect a pointer that has been deleted.
654+ for (int i = 0 ; i < reasons_.size (); ++i) {
655+ if (reasons_[i] != nullptr && reasons_[i]->empty ()) {
656+ reasons_[i] = nullptr ;
657+ }
658+ }
659+ }
660+
645661 int new_size = 0 ;
646662 const int old_size = clauses_.size ();
647663 for (int i = 0 ; i < old_size; ++i) {
648664 if (i == to_minimize_index_) to_minimize_index_ = new_size;
649665 if (i == to_first_minimize_index_) to_first_minimize_index_ = new_size;
650666 if (i == to_probe_index_) to_probe_index_ = new_size;
651667 if (clauses_[i]->IsRemoved ()) {
668+ DCHECK (!clauses_info_.contains (clauses_[i]));
652669 delete clauses_[i];
653670 } else {
654671 clauses_[new_size++] = clauses_[i];
0 commit comments