14#ifndef OR_TOOLS_SAT_PRESOLVE_UTIL_H_
15#define OR_TOOLS_SAT_PRESOLVE_UTIL_H_
24#include "absl/container/flat_hash_map.h"
25#include "absl/container/flat_hash_set.h"
26#include "absl/random/bit_gen_ref.h"
27#include "absl/random/random.h"
28#include "absl/strings/string_view.h"
29#include "absl/types/span.h"
33#include "ortools/sat/cp_model.pb.h"
65 if (count == 0)
return;
66 counters_.emplace_back(std::move(
name), count);
76 const std::string name_;
83 std::vector<std::pair<std::string, int64_t>> counters_;
84 std::vector<std::string> extra_infos_;
120 absl::Span<const int> clause);
133 Index IndexFromLiteral(
int ref)
const {
134 return Index(ref >= 0 ? 2 * ref : -2 * ref - 1);
137 std::vector<int> tmp_num_occurrences_;
141 absl::flat_hash_map<std::pair<Index, int>,
Domain> deductions_;
149 ConstraintProto* to_modify);
157 const ConstraintProto& definition, ConstraintProto*
ct);
199 absl::Span<
const std::pair<int, int64_t>> terms,
200 std::vector<std::array<int64_t, 2>>* conditional =
nullptr) {
201 return ComputeActivity(
false, terms, conditional);
204 absl::Span<
const std::pair<int, int64_t>> terms,
205 std::vector<std::array<int64_t, 2>>* conditional =
nullptr) {
206 return ComputeActivity(
true, terms, conditional);
218 absl::flat_hash_set<int>* literals_at_true);
226 absl::Span<
const std::pair<int, int64_t>> boolean_terms,
227 const Domain& other_terms,
const Domain& rhs, ConstraintProto*
ct);
232 absl::Span<const int> literals);
235 bool IsAmo(absl::Span<const int> literals);
239 const Index
i = IndexFromLiteral(
var);
241 return (
i < amo_indices_.size() ? amo_indices_[
i].size() : 0) +
242 (j < amo_indices_.size() ? amo_indices_[j].
size() : 0);
247 Index IndexFromLiteral(
int ref)
const {
248 return Index(ref >= 0 ? 2 * ref : -2 * ref - 1);
251 bool AppearInTriggeredAmo(
int literal);
253 int64_t ComputeActivity(
254 bool compute_min, absl::Span<
const std::pair<int, int64_t>> terms,
255 std::vector<std::array<int64_t, 2>>* conditional =
nullptr);
257 void PartitionIntoAmo(absl::Span<
const std::pair<int, int64_t>> terms);
261 int64_t ComputeMaxActivityInternal(
262 absl::Span<
const std::pair<int, int64_t>> terms,
263 std::vector<std::array<int64_t, 2>>* conditional =
nullptr);
267 int num_at_most_ones_ = 0;
270 std::vector<std::pair<int, int64_t>> tmp_terms_for_compute_activity_;
272 struct TermWithIndex {
277 std::vector<TermWithIndex> to_sort_;
280 absl::flat_hash_map<int, int> used_amo_to_dense_index_;
281 absl::flat_hash_map<int, int64_t> amo_sums_;
282 std::vector<int> partition_;
283 std::vector<int64_t> max_by_partition_;
284 std::vector<int64_t> second_max_by_partition_;
287 CompactVectorVector<int, int> part_to_literals_;
289 absl::flat_hash_set<int> triggered_amo_;
290 absl::flat_hash_set<int> tmp_set_;
305 return clause_to_hash_[c] ^ literal_to_hash_[IndexFromLiteral(ref)];
313 Index IndexFromLiteral(
int ref)
const {
314 return Index(ref >= 0 ? 2 * ref : -2 * ref - 1);
317 absl::BitGenRef random_;
319 std::vector<uint64_t> clause_to_hash_;
332 absl::Span<const int> enforcement,
334 if (clause.size() != enforcement.size() + 1)
return false;
336 for (
int i = 0;
i < clause.size(); ++
i) {
338 if (clause[
i] !=
NegatedRef(enforcement[j]))
return false;
346 const LinearConstraintProto& lin2,
int* var1,
347 int64_t* coeff1,
int* var2, int64_t* coeff2);
353 const LinearConstraintProto& lin2) {
355 int64_t coeff1, coeff2;
void Start()
When Start() is called multiple times, only the most recent is used.
void ClearAndResize(IntegerType size)
void AddAllAtMostOnes(const CpModelProto &proto)
int64_t ComputeMaxActivity(absl::Span< const std::pair< int, int64_t > > terms, std::vector< std::array< int64_t, 2 > > *conditional=nullptr)
void AddAtMostOne(absl::Span< const int > amo)
int RemoveEnforcementThatMakesConstraintTrivial(absl::Span< const std::pair< int, int64_t > > boolean_terms, const Domain &other_terms, const Domain &rhs, ConstraintProto *ct)
int64_t ComputeMinActivity(absl::Span< const std::pair< int, int64_t > > terms, std::vector< std::array< int64_t, 2 > > *conditional=nullptr)
ActivityBoundHelper()=default
std::vector< absl::Span< const int > > PartitionLiteralsIntoAmo(absl::Span< const int > literals)
Similar algo as above for this simpler case.
bool PresolveEnforcement(absl::Span< const int > refs, ConstraintProto *ct, absl::flat_hash_set< int > *literals_at_true)
bool IsAmo(absl::Span< const int > literals)
Returns true iff the given literal are in at most one relationship.
int NumAmoForVariable(int var) const
Returns in how many amo var or Not(var) are part of.
Class to help detects clauses that differ on a single literal.
uint64_t HashWithout(int c, int ref) const
void RegisterClause(int c, absl::Span< const int > clause)
We use the proto encoding of literals here.
ClauseWithOneMissingHasher(absl::BitGenRef random)
uint64_t HashOfNegatedLiterals(absl::Span< const int > literals)
Returns a hash of the negation of all the given literals.
int NumDeductions() const
Returns the total number of "deductions" stored by this class.
void MarkProcessingAsDoneForNow()
std::vector< std::pair< int, Domain > > ProcessClause(absl::Span< const int > clause)
void AddDeduction(int literal_ref, int var, Domain domain)
Domain ImpliedDomain(int literal_ref, int var) const
void AddToWork(double dtime)
void TrackSimpleLoop(int size)
void AddMessage(std::string name)
Extra info at the end of the log line.
bool WorkLimitIsReached() const
PresolveTimer(std::string name, SolverLogger *logger, TimeLimit *time_limit)
~PresolveTimer()
Update dtime and log operation summary.
void AddCounter(std::string name, int64_t count)
CpModelProto proto
The output proto.
const std::string name
A name for logging purposes.
bool FindSingleLinearDifference(const LinearConstraintProto &lin1, const LinearConstraintProto &lin2, int *var1, int64_t *coeff1, int *var2, int64_t *coeff2)
Same as LinearsDifferAtOneTerm() below but also fills the differing terms.
bool ClauseIsEnforcementImpliesLiteral(absl::Span< const int > clause, absl::Span< const int > enforcement, int literal)
bool SubstituteVariable(int var, int64_t var_coeff_in_definition, const ConstraintProto &definition, ConstraintProto *ct)
bool AddLinearConstraintMultiple(int64_t factor, const ConstraintProto &to_add, ConstraintProto *to_modify)
bool LinearsDifferAtOneTerm(const LinearConstraintProto &lin1, const LinearConstraintProto &lin2)
int NegatedRef(int ref)
Small utility functions to deal with negative variable/literal references.
In SWIG mode, we don't want anything besides these top-level includes.
#define DEFINE_STRONG_INDEX_TYPE(index_type_name)