14#ifndef OR_TOOLS_SAT_WORK_ASSIGNMENT_H_
15#define OR_TOOLS_SAT_WORK_ASSIGNMENT_H_
30#include "absl/base/thread_annotations.h"
31#include "absl/container/flat_hash_map.h"
32#include "absl/container/flat_hash_set.h"
33#include "absl/container/node_hash_map.h"
34#include "absl/log/check.h"
35#include "absl/synchronization/mutex.h"
36#include "absl/types/span.h"
44#include "ortools/sat/sat_parameters.pb.h"
62 return proto_var_ == other.proto_var_ && lb_ == other.lb_;
80 int proto_var_ = std::numeric_limits<int>::max();
109 int MaxLevel()
const {
return decision_indexes_.size(); }
114 CHECK_LE(level, decision_indexes_.size());
115 return literals_[decision_indexes_[level - 1]];
119 absl::Span<const int>
NodeIds(
int level)
const;
123 absl::Span<const ProtoLiteral>
Implications(
int level)
const;
125 auto it = implication_level_.find(implication);
126 if (it != implication_level_.end() && it->second <= level)
return;
127 MutableImplications(level).push_back(implication);
128 implication_level_[implication] = level;
133 return level_to_objective_lbs_[level - 1];
136 absl::Span<const ProtoLiteral>
Literals()
const {
return literals_; }
138 const std::vector<ProtoLiteral>&
TargetPhase()
const {
return target_phase_; }
140 target_phase_.clear();
142 if (implication_level_.contains(
lit))
return;
143 target_phase_.push_back(
lit);
148 std::vector<ProtoLiteral>& MutableImplications(
int level) {
149 return implications_[level - 1];
152 std::vector<ProtoLiteral> literals_;
153 std::vector<int> node_ids_;
157 std::vector<std::vector<ProtoLiteral>> implications_;
158 absl::flat_hash_map<ProtoLiteral, int> implication_level_;
161 std::vector<int> decision_indexes_;
164 std::vector<IntegerValue> level_to_objective_lbs_;
166 std::vector<ProtoLiteral> target_phase_;
182 int NumNodes() const ABSL_LOCKS_EXCLUDED(mu_);
201 absl::MutexLock l(&mu_);
210 struct NodeTrailInfo {
211 absl::flat_hash_set<ProtoLiteral> implications;
214 std::vector<ProtoLiteral> phase;
217 ProtoLiteral literal;
219 Node* parent =
nullptr;
220 std::array<Node*, 2> children = {
nullptr,
nullptr};
224 bool implied =
false;
226 std::unique_ptr<NodeTrailInfo> trail_info;
228 bool IsValid(
const ProtoTrail& path)
const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
229 Node* GetSibling(Node* node) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
232 NodeTrailInfo* GetTrailInfo(Node* node);
233 void Split(std::vector<std::pair<Node*, int>>&
nodes, ProtoLiteral
lit)
234 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
235 Node* MakeSubtree(Node* parent, ProtoLiteral
literal)
236 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
237 void ProcessNodeChanges() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
238 std::vector<
std::pair<Node*,
int>> GetAssignedNodes(const ProtoTrail& path)
239 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
240 void AssignLeaf(ProtoTrail& path, Node* leaf)
241 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
242 void RestartLockHeld() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
243 std::
string ShortStatus() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
245 mutable
absl::Mutex mu_;
246 const SatParameters& params_;
247 const
int num_workers_;
248 SharedResponseManager* const shared_response_manager_;
251 int node_id_offset_ ABSL_GUARDED_BY(mu_) = 0;
254 std::deque<Node> nodes_ ABSL_GUARDED_BY(mu_);
255 std::vector<Node*> unassigned_leaves_ ABSL_GUARDED_BY(mu_);
259 int num_splits_wanted_ ABSL_GUARDED_BY(mu_);
264 const
int max_nodes_;
265 int num_leaves_assigned_ ABSL_GUARDED_BY(mu_) = 0;
269 std::vector<Node*> to_close_ ABSL_GUARDED_BY(mu_);
270 std::vector<Node*> to_update_ ABSL_GUARDED_BY(mu_);
272 int64_t num_restarts_ ABSL_GUARDED_BY(mu_) = 0;
273 int64_t num_syncs_since_restart_ ABSL_GUARDED_BY(mu_) = 0;
274 int num_closed_nodes_ ABSL_GUARDED_BY(mu_) = 0;
284 const std::function<
void()>& feasible_solution_observer);
290 bool SyncWithLocalTrail();
291 bool SyncWithSharedTree();
293 std::optional<ProtoLiteral> EncodeDecision(
Literal decision);
294 bool NextDecision(LiteralIndex* decision_index);
295 void MaybeProposeSplit();
296 bool ShouldReplaceSubtree();
300 bool AddImplications();
303 const std::vector<Literal>& DecisionReason(
int level);
305 SatParameters* parameters_;
323 int64_t num_restarts_ = 0;
324 int64_t num_trees_ = 0;
327 std::vector<Literal> assigned_tree_literals_;
328 std::vector<std::vector<Literal>> assigned_tree_implications_;
330 int64_t tree_assignment_restart_ = -1;
336 bool new_split_available_ =
false;
338 std::vector<Literal> reason_;
346 int reversible_trail_index_ = 0;
349 std::deque<int> rev_num_processed_implications_;
---------------— Search class --------------—
An helper class to share the code used by the different kind of search.
static std::optional< ProtoLiteral > Encode(Literal, CpModelMapping *, IntegerEncoder *)
friend H AbslHashValue(H h, const ProtoLiteral &literal)
Literal Decode(CpModelMapping *, IntegerEncoder *) const
Note you should only decode integer literals at the root level.
ProtoLiteral(int var, IntegerValue lb)
ProtoLiteral Negated() const
bool operator==(const ProtoLiteral &other) const
bool operator!=(const ProtoLiteral &other) const
int MaxLevel() const
Returns the maximum decision level stored in the trail.
void SetPhase(absl::Span< const ProtoLiteral > phase)
void Clear()
Clear the trail, removing all levels.
ProtoLiteral Decision(int level) const
Returns the decision assigned at level.
void SetObjectiveLb(int level, IntegerValue objective_lb)
Set a lower bound on the objective at level.
absl::Span< const ProtoLiteral > Implications(int level) const
absl::Span< const int > NodeIds(int level) const
Returns the node ids for decisions and implications at level.
void AddImplication(int level, ProtoLiteral implication)
IntegerValue ObjectiveLb(int level) const
void PushLevel(const ProtoLiteral &decision, IntegerValue objective_lb, int node_id)
Adds a new assigned level to the trail.
absl::Span< const ProtoLiteral > Literals() const
const std::vector< ProtoLiteral > & TargetPhase() const
void SetLevelImplied(int level)
Asserts that the decision at level is implied by earlier decisions.
Contain the logic to decide when to restart a SAT tree search.
void CloseTree(ProtoTrail &path, int level)
SharedTreeManager(const SharedTreeManager &)=delete
SharedTreeManager(Model *model)
void ProposeSplit(ProtoTrail &path, ProtoLiteral decision)
void ReplaceTree(ProtoTrail &path)
Assigns a path prefix that the worker should explore.
bool SyncTree(ProtoTrail &path) ABSL_LOCKS_EXCLUDED(mu_)
int NumNodes() const ABSL_LOCKS_EXCLUDED(mu_)
SharedTreeWorker & operator=(const SharedTreeWorker &)=delete
SharedTreeWorker(const SharedTreeWorker &)=delete
DecisionBuilder *const phase
The decision builder we are going to use in this dive.
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue.value())
int NegatedRef(int ref)
Small utility functions to deal with negative variable/literal references.