Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
enforcement_helper.cc
Go to the documentation of this file.
1// Copyright 2010-2025 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 <functional>
17#include <vector>
18
19#include "absl/types/span.h"
21#include "ortools/sat/integer.h"
23#include "ortools/sat/model.h"
26
27namespace operations_research {
28namespace sat {
29
31 : enforcement_propagator_(*model->GetOrCreate<EnforcementPropagator>()),
32 assignment_(model->GetOrCreate<Trail>()->Assignment()),
33 integer_trail_(model->GetOrCreate<IntegerTrail>()) {}
34
36 absl::Span<const Literal> enforcement_literals,
37 GenericLiteralWatcher* watcher, int literal_watcher_id) {
38 return enforcement_propagator_.Register(
39 enforcement_literals, [=](EnforcementId, EnforcementStatus status) {
42 watcher->CallOnNextPropagate(literal_watcher_id);
43 }
44 });
45}
46
47// Try to propagate when the enforced constraint is not satisfiable.
48// This is currently in O(enforcement_size);
50 EnforcementId id, absl::Span<const Literal> literal_reason,
51 absl::Span<const IntegerLiteral> integer_reason) {
52 temp_reason_.clear();
53 LiteralIndex unique_unassigned = kNoLiteralIndex;
54 for (const Literal l : enforcement_propagator_.GetSpan(id)) {
55 if (assignment_.LiteralIsFalse(l)) return true;
56 if (assignment_.LiteralIsTrue(l)) {
57 temp_reason_.push_back(l.Negated());
58 continue;
59 }
60 if (unique_unassigned != kNoLiteralIndex) return true;
61 unique_unassigned = l.Index();
62 }
63
64 temp_reason_.insert(temp_reason_.end(), literal_reason.begin(),
65 literal_reason.end());
66 if (unique_unassigned == kNoLiteralIndex) {
67 return integer_trail_->ReportConflict(temp_reason_, integer_reason);
68 }
69
70 // We also change the status right away.
71 enforcement_propagator_.ChangeStatus(id, EnforcementStatus::IS_FALSE);
72 return integer_trail_->SafeEnqueueLiteral(
73 Literal(unique_unassigned).Negated(), temp_reason_, integer_reason);
74}
75
77 EnforcementId id, IntegerLiteral i_lit,
78 absl::Span<const Literal> literal_reason,
79 absl::Span<const IntegerLiteral> integer_reason) {
80 temp_reason_.clear();
81 temp_reason_.insert(temp_reason_.end(), literal_reason.begin(),
82 literal_reason.end());
83 enforcement_propagator_.AddEnforcementReason(id, &temp_reason_);
84 return integer_trail_->Enqueue(i_lit, temp_reason_, integer_reason);
85}
86
88 EnforcementId id, IntegerLiteral i_lit,
89 absl::Span<const IntegerLiteral> integer_reason) {
90 temp_reason_.clear();
91 enforcement_propagator_.AddEnforcementReason(id, &temp_reason_);
92 return integer_trail_->SafeEnqueue(i_lit, temp_reason_, integer_reason);
93}
94
96 EnforcementId id, Literal lit, IntegerLiteral i_lit,
97 absl::Span<const Literal> literal_reason,
98 absl::Span<const IntegerLiteral> integer_reason) {
99 temp_reason_.clear();
100 temp_reason_.insert(temp_reason_.end(), literal_reason.begin(),
101 literal_reason.end());
102 enforcement_propagator_.AddEnforcementReason(id, &temp_reason_);
103 temp_integer_reason_.clear();
104 temp_integer_reason_.insert(temp_integer_reason_.end(),
105 integer_reason.begin(), integer_reason.end());
106 return integer_trail_->ConditionalEnqueue(lit, i_lit, &temp_reason_,
107 &temp_integer_reason_);
108}
109
111 EnforcementId id, Literal literal, absl::Span<const Literal> literal_reason,
112 absl::Span<const IntegerLiteral> integer_reason) {
113 temp_reason_.clear();
114 temp_reason_.insert(temp_reason_.end(), literal_reason.begin(),
115 literal_reason.end());
116 enforcement_propagator_.AddEnforcementReason(id, &temp_reason_);
117 return integer_trail_->EnqueueLiteral(literal, temp_reason_, integer_reason);
118}
119
121 EnforcementId id, absl::Span<const Literal> literal_reason,
122 absl::Span<const IntegerLiteral> integer_reason) {
123 temp_reason_.clear();
124 temp_reason_.insert(temp_reason_.end(), literal_reason.begin(),
125 literal_reason.end());
126 enforcement_propagator_.AddEnforcementReason(id, &temp_reason_);
127 return integer_trail_->ReportConflict(temp_reason_, integer_reason);
128}
129
130} // namespace sat
131} // namespace operations_research
bool ReportConflict(EnforcementId id, absl::Span< const IntegerLiteral > integer_reason)
ABSL_MUST_USE_RESULT bool EnqueueLiteral(EnforcementId id, Literal literal, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
ABSL_MUST_USE_RESULT bool Enqueue(EnforcementId id, IntegerLiteral i_lit, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
EnforcementId Register(absl::Span< const Literal > enforcement_literals, GenericLiteralWatcher *watcher, int literal_watcher_id)
ABSL_MUST_USE_RESULT bool ConditionalEnqueue(EnforcementId id, Literal lit, IntegerLiteral i_lit, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
ABSL_MUST_USE_RESULT bool PropagateWhenFalse(EnforcementId id, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
ABSL_MUST_USE_RESULT bool SafeEnqueue(EnforcementId id, IntegerLiteral i_lit, absl::Span< const IntegerLiteral > integer_reason)
const LiteralIndex kNoLiteralIndex(-1)
OR-Tools root namespace.