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/log/check.h"
28#include "absl/strings/str_cat.h"
29#include "absl/strings/string_view.h"
30#include "absl/types/span.h"
32#include "ortools/sat/cp_model.pb.h"
36#include "ortools/sat/sat_parameters.pb.h"
91 params_(*
model->GetOrCreate<SatParameters>()),
106 absl::Span<
const std::pair<int, int64_t>> definition);
129 int64_t
MinOf(
int ref)
const;
130 int64_t
MaxOf(
int ref)
const;
139 int64_t
SizeMin(
int ct_ref)
const;
140 int64_t
SizeMax(
int ct_ref)
const;
141 int64_t
EndMin(
int ct_ref)
const;
142 int64_t
EndMax(
int ct_ref)
const;
148 int64_t
MinOf(
const LinearExpressionProto& expr)
const;
149 int64_t
MaxOf(
const LinearExpressionProto& expr)
const;
150 bool IsFixed(
const LinearExpressionProto& expr)
const;
151 int64_t
FixedValue(
const LinearExpressionProto& expr)
const;
156 template <
typename ProtoWithVarsAndCoeffs>
158 const ProtoWithVarsAndCoeffs&
proto)
const {
159 int64_t min_activity = 0;
160 int64_t max_activity = 0;
161 const int num_vars =
proto.vars().size();
162 for (
int i = 0;
i < num_vars; ++
i) {
164 const int64_t coeff =
proto.coeffs(
i);
173 return {min_activity, max_activity};
178 int64_t* max_activity) {
195 LinearExpressionProto* expr);
217 return domains[
var].IsIncludedIn(domain);
255 int ref,
const Domain& domain,
bool* domain_modified =
nullptr);
265 const LinearExpressionProto& expr,
const Domain& domain,
266 bool* domain_modified =
nullptr);
271 absl::string_view
message =
"") {
338 bool debug_no_recursion =
false);
487 int var_in_equality, int64_t coeff_in_equality,
488 const ConstraintProto& equality);
493 return objective_map_;
497 const auto it = objective_map_.find(
var);
498 return it == objective_map_.end() ? 0 : it->second;
501 return objective_domain_is_constraining_;
517 return constraint_to_vars_[c];
521 return var_to_constraints_[
var];
525 if (c >= interval_usage_.size())
return 0;
526 return interval_usage_[c];
559 const LinearExpressionProto& time_j,
560 int active_i,
int active_j);
562 std::tuple<int, int64_t, int, int64_t, int64_t, int, int>
564 const LinearExpressionProto& time_j,
int active_i,
582 const SatParameters&
params()
const {
return params_; }
629 void MaybeResizeIntervalData();
631 void EraseFromVarToConstraint(
int var,
int c);
636 void AddVariableUsage(
int c);
637 void UpdateLinear1Usage(
const ConstraintProto&
ct,
int c);
643 bool CanonicalizeEncoding(
int* ref, int64_t*
value);
657 void InsertVarValueEncodingInternal(
int literal,
int var, int64_t
value,
658 bool add_constraints);
661 const SatParameters& params_;
666 bool is_unsat_ =
false;
669 std::vector<Domain> domains;
675 bool hint_is_loaded_ =
false;
676 std::vector<bool> hint_has_value_;
677 std::vector<int64_t> hint_;
683 mutable bool objective_proto_is_up_to_date_ =
false;
684 absl::flat_hash_map<int, int64_t> objective_map_;
685 int64_t objective_overflow_detection_;
686 mutable std::vector<std::pair<int, int64_t>> tmp_entries_;
687 bool objective_domain_is_constraining_ =
false;
689 double objective_offset_;
690 double objective_scaling_factor_;
691 int64_t objective_integer_before_offset_;
692 int64_t objective_integer_after_offset_;
693 int64_t objective_integer_scaling_factor_;
696 std::vector<std::vector<int>> constraint_to_vars_;
697 std::vector<absl::flat_hash_set<int>> var_to_constraints_;
700 std::vector<int> constraint_to_linear1_var_;
701 std::vector<int> var_to_num_linear1_;
704 std::vector<std::vector<int>> constraint_to_intervals_;
705 std::vector<int> interval_usage_;
708 bool true_literal_is_defined_ =
false;
713 absl::flat_hash_map<int, absl::flat_hash_map<int64_t, SavedLiteral>>
720 absl::flat_hash_map<int,
721 absl::flat_hash_map<int64_t, absl::flat_hash_set<int>>>
723 absl::flat_hash_map<int,
724 absl::flat_hash_map<int64_t, absl::flat_hash_set<int>>>
734 absl::flat_hash_set<int> removed_variables_;
739 absl::flat_hash_map<std::tuple<int, int64_t, int, int64_t, int64_t, int, int>,
741 reified_precedences_cache_;
744 absl::flat_hash_map<std::string, int> stats_by_rule_name_;
747 std::vector<std::pair<int, int64_t>> tmp_terms_;
749 bool model_is_expanded_ =
false;
int NumRelations() const
Returns the number of relations added to the class and not ignored.
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 StoreBooleanEqualityRelation(int ref_a, int ref_b)
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.
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
bool VarHasSolutionHint(int var) const
Solution hint accessor.
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)
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
int NewIntVarWithDefinition(const Domain &domain, absl::Span< const std::pair< int, int64_t > > definition)
int64_t ObjectiveCoeff(int var) const
void ReadObjectiveFromProto()
ABSL_MUST_USE_RESULT bool NotifyThatModelIsUnsat(absl::string_view message="")
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
void AddImplyInDomain(int b, int x, const Domain &domain)
b => x in [lb, ub].
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
void LogInfo()
Logs stats to the logger.
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.
int64_t SolutionHint(int var) 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
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
ABSL_MUST_USE_RESULT bool ScaleFloatingPointObjective()
bool StoreAffineRelation(int ref_x, int ref_y, int64_t coeff, int64_t offset, bool debug_no_recursion=false)
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
bool PropagateAffineRelation(int ref)
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
bool keep_all_feasible_solutions
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 GetOrCreateReifiedPrecedenceLiteral(const LinearExpressionProto &time_i, const LinearExpressionProto &time_j, int active_i, int active_j)
bool CanonicalizeLinearConstraint(ConstraintProto *ct)
bool LiteralIsTrue(int lit) const
int Get(PresolveContext *context) const
CpModelProto proto
The output proto.
const std::string name
A name for logging purposes.
GurobiMPCallbackContext * context
bool LoadModelForProbing(PresolveContext *context, Model *local_model)
constexpr int kAffineRelationConstraint
constexpr int kAssumptionsConstraint
constexpr int kObjectiveConstraint
We use some special constraint index in our variable <-> constraint graph.
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)
#define SOLVER_LOG(logger,...)