14#ifndef OR_TOOLS_SAT_PRESOLVE_CONTEXT_H_
15#define OR_TOOLS_SAT_PRESOLVE_CONTEXT_H_
24#include "absl/base/attributes.h"
25#include "absl/container/flat_hash_map.h"
26#include "absl/container/flat_hash_set.h"
27#include "absl/flags/declare.h"
28#include "absl/log/check.h"
29#include "absl/strings/str_cat.h"
30#include "absl/strings/string_view.h"
31#include "absl/types/span.h"
33#include "ortools/sat/cp_model.pb.h"
37#include "ortools/sat/sat_parameters.pb.h"
91 const SatParameters& params,
SolverLogger* logger, CpModelProto* proto);
101 params_(*model->GetOrCreate<SatParameters>()),
102 time_limit_(model->GetOrCreate<
TimeLimit>()),
121 absl::Span<
const std::pair<int, int64_t>> definition,
122 bool append_constraint_to_mapping_model =
false);
153 int64_t
MinOf(
int ref)
const;
154 int64_t
MaxOf(
int ref)
const;
158 absl::Span<const Domain>
AllDomains()
const {
return domains_; }
164 int64_t
SizeMin(
int ct_ref)
const;
165 int64_t
SizeMax(
int ct_ref)
const;
166 int64_t
EndMin(
int ct_ref)
const;
167 int64_t
EndMax(
int ct_ref)
const;
173 int64_t
MinOf(
const LinearExpressionProto& expr)
const;
174 int64_t
MaxOf(
const LinearExpressionProto& expr)
const;
175 bool IsFixed(
const LinearExpressionProto& expr)
const;
176 int64_t
FixedValue(
const LinearExpressionProto& expr)
const;
180 const LinearExpressionProto& expr)
const;
185 template <
typename ProtoWithVarsAndCoeffs>
187 const ProtoWithVarsAndCoeffs& proto)
const {
188 int64_t min_activity = 0;
189 int64_t max_activity = 0;
190 const int num_vars = proto.vars().size();
191 for (
int i = 0;
i < num_vars; ++
i) {
192 const int var = proto.vars(
i);
193 const int64_t coeff = proto.coeffs(
i);
195 min_activity += coeff *
MinOf(var);
196 max_activity += coeff *
MaxOf(var);
198 min_activity += coeff *
MaxOf(var);
199 max_activity += coeff *
MinOf(var);
202 return {min_activity, max_activity};
207 int64_t* max_activity) {
224 LinearExpressionProto* expr);
227 bool DomainContains(
const LinearExpressionProto& expr, int64_t value)
const;
242 int* literal =
nullptr)
const;
246 return domains_[var].IsIncludedIn(domain);
284 int ref,
const Domain& domain,
bool* domain_modified =
nullptr);
294 const LinearExpressionProto& expr,
const Domain& domain,
295 bool* domain_modified =
nullptr);
300 absl::string_view message =
"") {
302 SOLVER_LOG(logger_,
"INFEASIBLE: '", message,
"'");
372 bool debug_no_recursion =
false);
530 int var_in_equality, int64_t coeff_in_equality,
531 const ConstraintProto& equality);
536 return objective_map_;
540 const auto it = objective_map_.find(var);
541 return it == objective_map_.end() ? 0 : it->second;
548 return objective_domain_is_constraining_;
569 return constraint_to_vars_[c];
573 return var_to_constraints_[var];
577 if (c >= interval_usage_.size())
return 0;
578 return interval_usage_[c];
611 const LinearExpressionProto& time_j,
612 int active_i,
int active_j);
614 std::tuple<int, int64_t, int, int64_t, int64_t, int, int>
616 const LinearExpressionProto& time_j,
int active_i,
639 const SatParameters&
params()
const {
return params_; }
676 absl::string_view
file,
int line);
679 void MaybeResizeIntervalData();
681 void EraseFromVarToConstraint(
int var,
int c);
684 bool AddRelation(
int x,
int y, int64_t c, int64_t o,
AffineRelation* repo);
686 void AddVariableUsage(
int c);
687 void UpdateLinear1Usage(
const ConstraintProto& ct,
int c);
693 bool CanonicalizeEncoding(
int* ref, int64_t* value);
703 bool InsertHalfVarValueEncoding(
int literal,
int var, int64_t value,
708 bool InsertVarValueEncodingInternal(
int literal,
int var, int64_t value,
709 bool add_constraints);
712 const SatParameters& params_;
717 bool is_unsat_ =
false;
720 std::vector<Domain> domains_;
728 mutable bool objective_proto_is_up_to_date_ =
false;
729 absl::flat_hash_map<int, int64_t> objective_map_;
730 int64_t objective_overflow_detection_;
731 mutable std::vector<std::pair<int, int64_t>> tmp_entries_;
732 bool objective_domain_is_constraining_ =
false;
734 double objective_offset_;
735 double objective_scaling_factor_;
736 int64_t objective_integer_before_offset_;
737 int64_t objective_integer_after_offset_;
738 int64_t objective_integer_scaling_factor_;
741 std::vector<std::vector<int>> constraint_to_vars_;
742 std::vector<absl::flat_hash_set<int>> var_to_constraints_;
745 std::vector<int> constraint_to_linear1_var_;
746 std::vector<int> var_to_num_linear1_;
749 std::vector<std::vector<int>> constraint_to_intervals_;
750 std::vector<int> interval_usage_;
753 bool true_literal_is_defined_ =
false;
758 absl::flat_hash_map<int, absl::flat_hash_map<int64_t, SavedLiteral>>
765 absl::flat_hash_map<std::tuple<int, int>, int64_t> eq_half_encoding_;
766 absl::flat_hash_map<std::tuple<int, int>, int64_t> neq_half_encoding_;
775 absl::flat_hash_set<int> removed_variables_;
780 absl::flat_hash_map<std::tuple<int, int64_t, int, int64_t, int64_t, int, int>,
782 reified_precedences_cache_;
785 absl::flat_hash_map<std::string, int> stats_by_rule_name_;
788 std::vector<std::pair<int, int64_t>> tmp_terms_;
790 bool model_is_expanded_ =
false;
799 absl::string_view name_for_logging);
803 std::vector<int>* variable_mapping,
804 CpModelProto* mini_model);
DomainDeductions deductions
Advanced presolve. See this class comment.
Domain DomainOf(int ref) const
const SatParameters & params() const
int IntervalUsage(int c) const
ABSL_MUST_USE_RESULT bool CanonicalizeObjective(bool simplify_domain=true)
bool ExpressionIsSingleVariable(const LinearExpressionProto &expr) const
Returns true iff the expr is of the form 1 * var + 0.
bool CanonicalizeAffineVariable(int ref, int64_t coeff, int64_t mod, int64_t rhs)
void RegisterVariablesUsedInAssumptions()
bool AddToObjectiveOffset(int64_t delta)
bool ObjectiveDomainIsConstraining() const
ABSL_MUST_USE_RESULT bool IntersectDomainWith(int ref, const Domain &domain, bool *domain_modified=nullptr)
bool ExpressionIsALiteral(const LinearExpressionProto &expr, int *literal=nullptr) const
Returns true iff the expr is a literal (x or not(x)).
CpModelProto * working_model
std::vector< Domain > tmp_term_domains
bool StoreLiteralImpliesVarEqValue(int literal, int var, int64_t value)
bool VariableIsUniqueAndRemovable(int ref) const
void ClearStats()
Clears the "rules" statistics.
bool StoreAffineRelation(int var_x, int var_y, int64_t coeff, int64_t offset, bool debug_no_recursion=false)
SparseBitset< int > modified_domains
Each time a domain is modified this is set to true.
ABSL_MUST_USE_RESULT bool SetLiteralToTrue(int lit)
bool LiteralIsFalse(int lit) const
void CanonicalizeVariable(int ref)
bool VariableWithCostIsUniqueAndRemovable(int ref) const
int NewIntVarWithDefinition(const Domain &domain, absl::Span< const std::pair< int, int64_t > > definition, bool append_constraint_to_mapping_model=false)
bool DomainIsEmpty(int ref) const
Helpers to query the current domain of a variable.
ABSL_MUST_USE_RESULT bool SubstituteVariableInObjective(int var_in_equality, int64_t coeff_in_equality, const ConstraintProto &equality)
int64_t FixedValue(int ref) const
void AddImplication(int a, int b)
a => b.
bool IntervalIsConstant(int ct_ref) const
Helper to query the state of an interval.
int NewIntVar(const Domain &domain)
Helpers to adds new variables to the presolved model.
bool DebugTestHintFeasibility()
bool ShiftCostInExactlyOne(absl::Span< const int > exactly_one, int64_t shift)
ABSL_MUST_USE_RESULT bool SetLiteralToFalse(int lit)
Returns false if the 'lit' doesn't have the desired value in the domain.
absl::Span< const int > ConstraintToVars(int c) const
int64_t ObjectiveCoeff(int var) const
void ReadObjectiveFromProto()
ABSL_MUST_USE_RESULT bool NotifyThatModelIsUnsat(absl::string_view message="")
bool HasUnusedAffineVariable() const
void CanonicalizeDomainOfSizeTwo(int var)
int GetOrCreateVarValueEncoding(int ref, int64_t value)
int64_t num_presolve_operations
int64_t SizeMax(int ct_ref) const
ABSL_MUST_USE_RESULT bool CanonicalizeOneObjectiveVariable(int var)
std::string IntervalDebugString(int ct_ref) const
bool ExpressionIsAffineBoolean(const LinearExpressionProto &expr) const
void WriteObjectiveToProto() const
bool IsFixed(int ref) const
int64_t EndMin(int ct_ref) const
bool VariableIsOnlyUsedInLinear1AndOneExtraConstraint(int var) const
int64_t EndMax(int ct_ref) const
bool StoreBooleanEqualityRelation(int ref_a, int ref_b)
void AddImplyInDomain(int b, int x, const Domain &domain)
b => (x ∈ domain).
int64_t SizeMin(int ct_ref) const
bool RecomputeSingletonObjectiveDomain()
bool VariableIsOnlyUsedInEncodingAndMaybeInObjective(int var) const
std::tuple< int, int64_t, int, int64_t, int64_t, int, int > GetReifiedPrecedenceKey(const LinearExpressionProto &time_i, const LinearExpressionProto &time_j, int active_i, int active_j)
void CappedUpdateMinMaxActivity(int var, int64_t coeff, int64_t *min_activity, int64_t *max_activity)
Utility function.
std::pair< int64_t, int64_t > ComputeMinMaxActivity(const ProtoWithVarsAndCoeffs &proto) const
int NewBoolVar(absl::string_view source)
void LogInfo()
Logs stats to the logger.
void RemoveNonRepresentativeAffineVariableIfUnused(int var)
void ClearPrecedenceCache()
Clear the precedence cache.
bool IsFullyEncoded(int ref) const
void NotifyThatModelIsExpanded()
bool ConstraintIsInactive(int ct_index) const
std::vector< Domain > tmp_left_domains
int NewBoolVarWithClause(absl::Span< const int > clause)
bool HasVarValueEncoding(int ref, int64_t value, int *literal=nullptr)
void RemoveVariableFromObjective(int ref)
Allows to manipulate the objective coefficients.
std::optional< int64_t > FixedValueOrNullopt(const LinearExpressionProto &expr) const
This is faster than testing IsFixed() + FixedValue().
absl::Span< const Domain > AllDomains() const
bool ConstraintIsOptional(int ct_ref) const
void RemoveAllVariablesFromAffineRelationConstraint()
const Domain & ObjectiveDomain() const
Objective getters.
Domain DomainSuperSetOf(const LinearExpressionProto &expr) const
Return a super-set of the domain of the linear expression.
bool ModelIsExpanded() const
bool PropagateAffineRelation(int var)
void InitializeNewDomains()
Creates the internal structure for any new variables in working_model.
bool VariableIsNotUsedAnymore(int ref) const
Returns true if this ref no longer appears in the model.
absl::flat_hash_set< int > tmp_literal_set
bool VariableIsUnique(int ref) const
Returns true if this ref only appear in one constraint.
bool VariableWasRemoved(int ref) const
ConstraintProto * NewMappingConstraint(absl::string_view file, int line)
bool ConstraintVariableGraphIsUpToDate() const
int64_t StartMax(int ct_ref) const
int GetLiteralRepresentative(int ref) const
Returns the representative of a literal.
int GetOrCreateAffineValueEncoding(const LinearExpressionProto &expr, int64_t value)
int LiteralForExpressionMax(const LinearExpressionProto &expr) const
void UpdateConstraintVariableUsage(int c)
SparseBitset< int > var_with_reduced_small_degree
std::vector< int > tmp_literals
Temporary storage.
bool CanonicalizeLinearExpression(absl::Span< const int > enforcements, LinearExpressionProto *expr)
bool DomainOfVarIsIncludedIn(int var, const Domain &domain)
This function takes a positive variable reference.
void UpdateRuleStats(const std::string &name, int num_times=1)
AffineRelation::Relation GetAffineRelation(int ref) const
Returns the representative of ref under the affine relations.
void AddToObjective(int var, int64_t value)
const absl::flat_hash_set< int > & VarToConstraints(int var) const
SolverLogger * logger() const
std::string RefDebugString(int ref) const
To facilitate debugging.
void MarkVariableAsRemoved(int ref)
void AddLiteralToObjective(int ref, int64_t value)
void WriteVariableDomainsToProto() const
bool InsertVarValueEncoding(int literal, int var, int64_t value)
void UpdateNewConstraintsVariableUsage()
Calls UpdateConstraintVariableUsage() on all newly created constraints.
int NumAffineRelations() const
Used for statistics.
bool CanBeUsedAsLiteral(int ref) const
PresolveContext(Model *model, CpModelProto *cp_model, CpModelProto *mapping)
const absl::flat_hash_map< int, int64_t > & ObjectiveMap() const
bool ConstraintVariableUsageIsConsistent()
int64_t StartMin(int ct_ref) const
std::string AffineRelationDebugString(int ref) const
int64_t MinOf(int ref) const
bool StoreLiteralImpliesVarNEqValue(int literal, int var, int64_t value)
int64_t MaxOf(int ref) const
void RemoveVariableFromAffineRelation(int var)
ModelRandomGenerator * random()
bool ExploitExactlyOneInObjective(absl::Span< const int > exactly_one)
bool VariableWithCostIsUnique(int ref) const
CpModelProto * mapping_model
bool DomainContains(int ref, int64_t value) const
bool ModelIsUnsat() const
int NewBoolVarWithConjunction(absl::Span< const int > conjunction)
int GetOrCreateReifiedPrecedenceLiteral(const LinearExpressionProto &time_i, const LinearExpressionProto &time_j, int active_i, int active_j)
bool CanonicalizeLinearConstraint(ConstraintProto *ct)
SolutionCrush & solution_crush()
bool LiteralIsTrue(int lit) const
int Get(PresolveContext *context) const
bool LoadModelForProbing(PresolveContext *context, Model *local_model)
bool ScaleFloatingPointObjective(const SatParameters ¶ms, SolverLogger *logger, CpModelProto *proto)
constexpr int kAffineRelationConstraint
constexpr int kAssumptionsConstraint
constexpr int kObjectiveConstraint
We use some special constraint index in our variable <-> constraint graph.
void CreateValidModelWithSingleConstraint(const ConstraintProto &ct, const PresolveContext *context, std::vector< int > *variable_mapping, CpModelProto *mini_model)
bool LoadModelForPresolve(const CpModelProto &model_proto, SatParameters params, PresolveContext *context, Model *local_model, absl::string_view name_for_logging)
In SWIG mode, we don't want anything besides these top-level includes.
int64_t CapAdd(int64_t x, int64_t y)
int64_t CapProd(int64_t x, int64_t y)
ABSL_DECLARE_FLAG(bool, cp_model_debug_postsolve)
#define SOLVER_LOG(logger,...)