125 int MaxLevel()
const {
return decision_indexes_.size(); }
130 CHECK_LE(level, decision_indexes_.size());
131 return literals_[decision_indexes_[level - 1]];
138 absl::Span<const int>
NodeIds(
int level)
const;
142 absl::Span<const ProtoLiteral>
Implications(
int level)
const;
149 auto it = assigned_at_level_.find(implication);
150 if (it != assigned_at_level_.end() && it->second <= level)
return false;
151 MutableImplications(level).push_back(implication);
152 assigned_at_level_[implication] = level;
162 return level_to_objective_lbs_[level - 1];
165 absl::Span<const ProtoLiteral>
Literals()
const {
return literals_; }
167 const std::vector<ProtoLiteral>&
TargetPhase()
const {
return target_phase_; }
171 return std::move(target_phase_);
176 if (target_phase_.size() >= kMaxPhaseSize)
return false;
178 target_phase_.push_back(lit);
183 target_phase_ = std::move(phase);
186 return assigned_at_level_.contains(lit) ||
187 assigned_at_level_.contains(lit.
Negated());
192 static constexpr int kMaxPhaseSize = 256;
194 std::vector<ProtoLiteral>& MutableImplications(
int level) {
195 return implications_[level - 1];
198 std::vector<ProtoLiteral> literals_;
199 std::vector<int> node_ids_;
203 std::vector<std::vector<ProtoLiteral>> implications_;
204 absl::flat_hash_map<ProtoLiteral, int> assigned_at_level_;
207 std::vector<int> decision_indexes_;
210 std::vector<IntegerValue> level_to_objective_lbs_;
212 std::vector<ProtoLiteral> target_phase_;
228 int NumNodes() const ABSL_LOCKS_EXCLUDED(mu_);
250 ABSL_LOCKS_EXCLUDED(mu_);
253 absl::MutexLock l(mu_);
264 struct NodeTrailInfo {
268 absl::flat_hash_map<int, std::pair<IntegerValue, ClauseId>> implications;
271 std::vector<ProtoLiteral> phase;
274 ProtoLiteral decision;
276 Node* parent =
nullptr;
277 std::array<Node*, 2> children = {
nullptr,
nullptr};
287 bool implied =
false;
288 bool implied_and_processed =
false;
290 std::unique_ptr<NodeTrailInfo> trail_info;
292 bool IsValid(
const ProtoTrail& path)
const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
293 Node* GetSibling(
const Node* node)
const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
296 NodeTrailInfo* GetTrailInfo(Node* node);
297 void ClearTrailInfo(Node* node,
bool implications_only =
false);
298 bool TrySplitTreeLockHeld(ProtoLiteral decision, ProtoTrail& path)
299 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
300 void Split(std::vector<std::pair<Node*, int>>& nodes, ProtoLiteral lit)
301 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
302 Node* MakeSubtree(Node* parent, ProtoLiteral decision)
303 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
304 void ProcessNodeChanges() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
305 void ProcessImpliedNode(Node* node) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
306 void UpdateLratClausesInSubtree(Node* node, Node* n,
307 std::vector<ClauseId>& clauses)
308 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
309 Node* GetNode(
int node_id) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
310 std::vector<std::pair<Node*,
int>> GetAssignedNodes(const ProtoTrail& path)
311 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
312 void AssignLeaf(ProtoTrail& path, Node* leaf)
313 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
314 void RestartLockHeld() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
315 std::
string ShortStatus() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
318 bool IsDecisionOfNodeOrAncestor(ProtoLiteral literal, const Node* node) const
319 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
325 std::vector<Literal> ImplicationClause(
326 const Node* node, ProtoLiteral implied,
327 bool skip_unprocessed_implied_nodes = false) const
328 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
334 std::vector<Literal> ClosingClause(
335 const Node* node,
bool skip_unprocessed_implied_nodes = false) const
336 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
343 ClauseId AddImportedAndInferredClauses(
344 absl::Span<const Literal> imported_clause,
345 absl::Span<const Literal> inferred_clause,
346 std::vector<ClauseId>& lrat_proof) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
348 bool CheckLratInvariants() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
350 mutable absl::Mutex mu_;
351 const SatParameters& params_;
352 const
int num_workers_;
353 const
int max_path_depth_;
354 SharedResponseManager* const shared_response_manager_;
355 ClauseIdGenerator clause_id_generator_;
356 std::unique_ptr<LratProofHandler> lrat_proof_handler_;
359 int node_id_offset_ ABSL_GUARDED_BY(mu_) = 0;
362 std::deque<Node> nodes_ ABSL_GUARDED_BY(mu_);
363 std::deque<Node*> unassigned_leaves_ ABSL_GUARDED_BY(mu_);
367 int num_splits_wanted_ ABSL_GUARDED_BY(mu_);
372 const
int max_nodes_;
373 int num_leaves_assigned_since_restart_ ABSL_GUARDED_BY(mu_) = 0;
379 std::vector<std::pair<Node*, ClauseId>> to_close_ ABSL_GUARDED_BY(mu_);
380 std::vector<Node*> to_update_ ABSL_GUARDED_BY(mu_);
382 int64_t num_restarts_ ABSL_GUARDED_BY(mu_) = 0;
383 int num_closed_nodes_ ABSL_GUARDED_BY(mu_) = 0;
393 const std::function<
void()>& feasible_solution_observer);
399 bool SyncWithLocalTrail();
400 bool SyncWithSharedTree();
402 std::optional<ProtoLiteral> EncodeDecision(
Literal decision);
403 bool NextDecision(LiteralIndex* decision_index);
404 void MaybeProposeSplits();
405 bool ShouldReplaceSubtree();
406 bool FinishedMinRestarts()
const {
407 return assigned_tree_.MaxLevel() > 0 &&
408 restart_policy_->NumRestarts() >=
409 parameters_->shared_tree_worker_min_restarts_per_subtree();
414 bool AddImplications();
415 bool AddDecisionImplication(
Literal literal,
int level, ClauseId clause_id);
417 void ClearAssignedTreeDecisionsAndImplications();
421 ClauseId AddLratClauseAndProofForImplication(
423 std::optional<absl::FunctionRef<ClauseId(
int,
int)>> root_literals = {});
427 ClauseId ImportLratClauseForImplication(Literal literal,
int level);
429 std::vector<Literal>& DecisionReason(
int level);
431 bool CheckLratInvariants();
433 SatParameters* parameters_;
434 SharedResponseManager* shared_response_;
437 CpModelMapping* mapping_;
438 SatSolver* sat_solver_;
440 BinaryImplicationGraph* binary_propagator_;
441 ClauseManager* clause_manager_;
442 ClauseIdGenerator* clause_id_generator_;
443 LratProofHandler* lrat_proof_handler_;
444 IntegerTrail* integer_trail_;
445 IntegerEncoder* encoder_;
446 const ObjectiveDefinition* objective_;
447 ModelRandomGenerator* random_;
448 IntegerSearchHelper* helper_;
449 SearchHeuristics* heuristics_;
450 SatDecisionPolicy* decision_policy_;
451 RestartPolicy* restart_policy_;
452 LevelZeroCallbackHelper* level_zero_callbacks_;
453 RevIntRepository* reversible_int_repository_;
455 int64_t num_trees_ = 0;
457 ProtoTrail assigned_tree_;
458 std::vector<Literal> assigned_tree_decisions_;
462 std::vector<std::vector<std::pair<Literal, ClauseId>>>
463 assigned_tree_implications_;
464 double next_split_dtime_ = 0;
469 std::vector<ClauseId> trail_implication_clauses_;
471 std::vector<ProtoLiteral> tmp_splits_;
472 std::vector<Literal> reason_;
478 double earliest_replacement_dtime_ = 0;
481 int reversible_trail_index_ = 0;
484 std::deque<int> rev_num_processed_implications_;