14#ifndef OR_TOOLS_SAT_CONSTRAINT_VIOLATION_H_
15#define OR_TOOLS_SAT_CONSTRAINT_VIOLATION_H_
24#include "absl/container/flat_hash_map.h"
25#include "absl/types/span.h"
26#include "ortools/sat/cp_model.pb.h"
27#include "ortools/sat/sat_parameters.pb.h"
69 int var, int64_t
delta, absl::Span<const double> weights,
70 absl::Span<const int64_t> jump_deltas, absl::Span<double> jump_scores,
71 std::vector<int>* constraints_with_changed_violations);
75 absl::Span<double> var_to_score_change);
83 return last_affected_variables_;
109 int64_t
delta)
const;
118 const Domain& var_domain)
const;
124 return 5e-9 *
static_cast<double>(num_ops_);
128 if (
var >= columns_.size())
return 0.0;
129 const SpanData& data = columns_[
var];
130 if (data.num_linear_entries == 0)
return 0.0;
131 const int i = data.start + data.num_neg_literal + data.num_pos_literal;
132 const int c = ct_buffer_[
i];
133 if (c != 0)
return 0.0;
134 return coeff_buffer_[data.linear_start];
138 const SpanData& data = rows_[c];
140 data.num_pos_literal + data.num_neg_literal + data.num_linear_entries;
141 if (
size == 0)
return {};
142 return absl::MakeSpan(&row_var_buffer_[data.start],
size);
153 struct LiteralEntry {
160 int num_pos_literal = 0;
161 int num_neg_literal = 0;
162 int linear_start = 0;
163 int num_linear_entries = 0;
166 absl::Span<const int> VarToConstraints(
int var)
const {
167 if (
var >= columns_.size())
return {};
168 const SpanData& data = columns_[
var];
170 data.num_pos_literal + data.num_neg_literal + data.num_linear_entries;
171 if (
size == 0)
return {};
172 return absl::MakeSpan(&ct_buffer_[data.start],
size);
175 void ComputeAndCacheDistance(
int ct_index);
178 void UpdateScoreOnNewlyEnforced(
int c,
double weight,
179 absl::Span<const int64_t> jump_deltas,
180 absl::Span<double> jump_scores);
181 void UpdateScoreOnNewlyUnenforced(
int c,
double weight,
182 absl::Span<const int64_t> jump_deltas,
183 absl::Span<double> jump_scores);
184 void UpdateScoreOfEnforcementIncrease(
int c,
double score_change,
185 absl::Span<const int64_t> jump_deltas,
186 absl::Span<double> jump_scores);
187 void UpdateScoreOnActivityChange(
int c,
double weight, int64_t activity_delta,
188 absl::Span<const int64_t> jump_deltas,
189 absl::Span<double> jump_scores);
192 int num_constraints_ = 0;
193 std::vector<Domain> domains_;
194 std::vector<int64_t> offsets_;
199 bool creation_phase_ =
true;
200 std::vector<std::vector<Entry>> var_entries_;
201 std::vector<std::vector<LiteralEntry>> literal_entries_;
204 std::vector<SpanData> columns_;
205 std::vector<int> ct_buffer_;
206 std::vector<int64_t> coeff_buffer_;
209 std::vector<SpanData> rows_;
210 std::vector<int> row_var_buffer_;
211 std::vector<int64_t> row_coeff_buffer_;
217 std::vector<int64_t> row_max_variations_;
220 std::vector<int> tmp_row_sizes_;
221 std::vector<int> tmp_row_num_positive_literals_;
222 std::vector<int> tmp_row_num_negative_literals_;
223 std::vector<int> tmp_row_num_linear_entries_;
226 std::vector<bool> is_violated_;
227 std::vector<int64_t> activities_;
228 std::vector<int64_t> distances_;
229 std::vector<int> num_false_enforcement_;
232 std::vector<int64_t> old_distances_;
233 std::vector<int> old_num_false_enforcement_;
234 std::vector<int64_t> cached_deltas_;
235 std::vector<double> cached_scores_;
237 std::vector<bool> in_last_affected_variables_;
238 FixedCapacityVector<int> last_affected_variables_;
240 mutable size_t num_ops_ = 0;
254 absl::Span<const int64_t> solution_with_new_value);
258 int var, int64_t old_value,
259 absl::Span<const int64_t> solution_with_new_value);
267 const CpModelProto& model_proto)
const = 0;
289 const ConstraintProto&
ct_proto()
const {
return ct_proto_; }
292 std::vector<int>
UsedVariables(
const CpModelProto& model_proto)
const final;
295 const ConstraintProto& ct_proto_;
309 LsEvaluator(
const CpModelProto& cp_model,
const SatParameters& params);
310 LsEvaluator(
const CpModelProto& cp_model,
const SatParameters& params,
311 const std::vector<bool>& ignored_constraints,
312 const std::vector<ConstraintProto>& additional_constraints);
324 absl::Span<const int64_t> new_solution);
328 absl::Span<const double> weights,
329 absl::Span<const int64_t> jump_deltas,
330 absl::Span<double> jump_scores);
347 return cp_model_.has_objective() && c == 0;
351 return cp_model_.has_objective()
374 absl::Span<const double> weights,
int var,
376 absl::Span<int64_t> mutable_solution)
const;
379 return linear_evaluator_;
383 return &linear_evaluator_;
393 return violated_constraints_.values();
398 return num_violated_constraint_per_var_ignoring_objective_[
var];
405 return last_update_violation_changes_;
418 return var_to_constraints_[
var];
421 return constraint_to_vars_[general_c];
430 void CompileConstraintsAndObjective(
431 const std::vector<bool>& ignored_constraints,
432 const std::vector<ConstraintProto>& additional_constraints);
434 void CompileOneConstraint(
const ConstraintProto& ct_proto);
435 void BuildVarConstraintGraph();
438 const CpModelProto& cp_model_;
439 const SatParameters& params_;
440 CpModelProto expanded_constraints_;
442 std::vector<std::unique_ptr<CompiledConstraint>> constraints_;
443 std::vector<std::vector<int>> var_to_constraints_;
444 std::vector<std::vector<int>> constraint_to_vars_;
445 std::vector<bool> jump_value_optimal_;
448 std::vector<int> num_violated_constraint_per_var_ignoring_objective_;
451 std::vector<int> last_update_violation_changes_;
453 mutable double dtime_ = 0;
461class CompiledBoolXorConstraint :
public CompiledConstraintWithProto {
469 absl::Span<const int64_t> solution_with_new_value)
override;
534 std::vector<int64_t> values_;
543 const CpModelProto& cp_model);
547 return ComputeViolationInternal(
solution);
554 absl::Span<const int64_t> solution_with_new_value)
final {
555 return ComputeViolationInternal(solution_with_new_value) -
violation();
558 std::vector<int>
UsedVariables(
const CpModelProto& model_proto)
const final;
561 int64_t ComputeViolationInternal(absl::Span<const int64_t>
solution);
563 int num_enforcements_;
564 std::unique_ptr<int[]> enforcements_;
565 LinearExpressionProto end_minus_start_1_;
566 LinearExpressionProto end_minus_start_2_;
569class CompiledNoOverlap2dConstraint :
public CompiledConstraintWithProto {
572 const CpModelProto& cp_model);
578 const CpModelProto& cp_model_;
592 std::vector<std::optional<int>> is_active,
593 std::vector<LinearExpressionProto> times,
594 std::vector<LinearExpressionProto> demands)
595 : capacity_(
std::move(capacity)),
596 is_active_(
std::move(is_active)),
597 times_(
std::move(times)),
598 demands_(
std::move(demands)) {
599 const int num_events = times_.size();
600 time_values_.resize(num_events, 0);
601 demand_values_.resize(num_events, 0);
602 InitializeDenseIndexToEvents();
614 absl::Span<const int64_t> solution_with_new_value)
final {
623 absl::Span<const int64_t> solution_with_new_value)
final {
624 return IncrementalViolation(
var, solution_with_new_value) -
violation_;
627 std::vector<int>
UsedVariables(
const CpModelProto& model_proto)
const final;
631 int64_t BuildProfileAndReturnViolation(absl::Span<const int64_t>
solution);
635 int64_t IncrementalViolation(
int var, absl::Span<const int64_t>
solution);
638 void InitializeDenseIndexToEvents();
639 void AppendVariablesForEvent(
int i, std::vector<int>* result)
const;
643 const LinearExpressionProto capacity_;
644 const std::vector<std::optional<int>> is_active_;
645 const std::vector<LinearExpressionProto> times_;
646 const std::vector<LinearExpressionProto> demands_;
649 absl::flat_hash_map<int, int> var_to_dense_index_;
655 bool operator<(
const Event& o)
const {
return time < o.time; }
657 std::vector<Event> profile_;
658 std::vector<Event> profile_delta_;
662 int64_t capacity_value_;
663 std::vector<int64_t> time_values_;
664 std::vector<int64_t> demand_values_;
int64_t ComputeViolation(absl::Span< const int64_t > solution) override
CompiledAllDiffConstraint(const ConstraintProto &ct_proto)
--— CompiledAllDiffConstraint --—
~CompiledAllDiffConstraint() override=default
~CompiledBoolXorConstraint() override=default
CompiledBoolXorConstraint(const ConstraintProto &ct_proto)
--— CompiledBoolXorConstraint --—
int64_t ViolationDelta(int, int64_t, absl::Span< const int64_t > solution_with_new_value) override
Returns the delta if var changes from old_value to solution[var].
int64_t ComputeViolation(absl::Span< const int64_t > solution) override
CompiledConstraintWithProto(const ConstraintProto &ct_proto)
--— CompiledConstraintWithProto --—
std::vector< int > UsedVariables(const CpModelProto &model_proto) const final
This just returns the variables used by the stored ct_proto_.
~CompiledConstraintWithProto() override=default
const ConstraintProto & ct_proto() const
View of a generic (non linear) constraint for the LsEvaluator.
int64_t violation() const
The cached violation of this constraint.
virtual std::vector< int > UsedVariables(const CpModelProto &model_proto) const =0
virtual void PerformMove(int var, int64_t old_value, absl::Span< const int64_t > solution_with_new_value)
Updates the violation with the new value.
virtual int64_t ComputeViolation(absl::Span< const int64_t > solution)=0
void InitializeViolation(absl::Span< const int64_t > solution)
Recomputes the violation of the constraint from scratch.
CompiledConstraint()=default
virtual int64_t ViolationDelta(int var, int64_t old_value, absl::Span< const int64_t > solution_with_new_value)
Returns the delta if var changes from old_value to solution[var].
virtual ~CompiledConstraint()=default
~CompiledIntDivConstraint() override=default
CompiledIntDivConstraint(const ConstraintProto &ct_proto)
--— CompiledIntDivConstraint --—
int64_t ComputeViolation(absl::Span< const int64_t > solution) override
int64_t ComputeViolation(absl::Span< const int64_t > solution) override
~CompiledIntModConstraint() override=default
CompiledIntModConstraint(const ConstraintProto &ct_proto)
--— CompiledIntModConstraint --—
CompiledIntProdConstraint(const ConstraintProto &ct_proto)
--— CompiledIntProdConstraint --—
~CompiledIntProdConstraint() override=default
int64_t ComputeViolation(absl::Span< const int64_t > solution) override
int64_t ComputeViolation(absl::Span< const int64_t > solution) override
CompiledLinMaxConstraint(const ConstraintProto &ct_proto)
--— CompiledLinMaxConstraint --—
~CompiledLinMaxConstraint() override=default
int64_t ComputeViolation(absl::Span< const int64_t > solution) override
CompiledNoOverlap2dConstraint(const ConstraintProto &ct_proto, const CpModelProto &cp_model)
~CompiledNoOverlap2dConstraint() override=default
CompiledReservoirConstraint(LinearExpressionProto capacity, std::vector< std::optional< int > > is_active, std::vector< LinearExpressionProto > times, std::vector< LinearExpressionProto > demands)
void PerformMove(int, int64_t, absl::Span< const int64_t > solution_with_new_value) final
Updates the violation with the new value.
int64_t ComputeViolation(absl::Span< const int64_t > solution) final
int64_t ViolationDelta(int var, int64_t, absl::Span< const int64_t > solution_with_new_value) final
Returns the delta if var changes from old_value to solution[var].
std::vector< int > UsedVariables(const CpModelProto &model_proto) const final
void UpdateScoreOnWeightUpdate(int c, absl::Span< const int64_t > jump_deltas, absl::Span< double > var_to_score_change)
Also for feasibility jump.
void AddOffset(int ct_index, int64_t offset)
double WeightedViolationDelta(absl::Span< const double > weights, int var, int64_t delta) const
bool IsViolated(int c) const
void ComputeInitialActivities(absl::Span< const int64_t > solution)
Compute activities.
void AddLiteral(int ct_index, int lit, int64_t coeff=1)
int NewConstraint(Domain domain)
Returns the index of the new constraint.
double WeightedViolation(absl::Span< const double > weights) const
bool ReduceBounds(int c, int64_t lb, int64_t ub)
bool VarIsConsistent(int var) const
Used to DCHECK the state of the evaluator.
int64_t ObjectiveCoefficient(int var) const
int num_constraints() const
Model getters.
void ClearAffectedVariables()
int64_t Activity(int c) const
Query violation.
void UpdateVariableAndScores(int var, int64_t delta, absl::Span< const double > weights, absl::Span< const int64_t > jump_deltas, absl::Span< double > jump_scores, std::vector< int > *constraints_with_changed_violations)
double DeterministicTime() const
bool AppearsInViolatedConstraints(int var) const
absl::Span< const int > VariablesAffectedByLastUpdate() const
void AddLinearExpression(int ct_index, const LinearExpressionProto &expr, int64_t multiplier)
void PrecomputeCompactView(absl::Span< const int64_t > var_max_variation)
int64_t Violation(int c) const
absl::Span< const int > ConstraintToVars(int c) const
void AddEnforcementLiteral(int ct_index, int lit)
bool ViolationChangeIsConvex(int var) const
Checks if the jump value of a variable is always optimal.
LinearIncrementalEvaluator()=default
std::vector< int64_t > SlopeBreakpoints(int var, int64_t current_value, const Domain &var_domain) const
void AddTerm(int ct_index, int var, int64_t coeff, int64_t offset=0)
int NumViolatedConstraintsForVarIgnoringObjective(int var) const
Returns the number of constraints in ViolatedConstraints containing var.
double WeightedViolation(absl::Span< const double > weights) const
void ComputeAllNonLinearViolations(absl::Span< const int64_t > solution)
const LinearIncrementalEvaluator & LinearEvaluator()
void UpdateLinearScores(int var, int64_t old_value, int64_t new_value, absl::Span< const double > weights, absl::Span< const int64_t > jump_deltas, absl::Span< double > jump_scores)
Function specific to the linear only feasibility jump.
bool VariableOnlyInLinearConstraintWithConvexViolationChange(int var) const
Indicates if the computed jump value is always the best choice.
void ComputeAllViolations(absl::Span< const int64_t > solution)
Recomputes the violations of all constraints (resp only non-linear one).
void UpdateNonLinearViolations(int var, int64_t old_value, absl::Span< const int64_t > new_solution)
Recomputes the violations of all impacted non linear constraints.
double DeterministicTime() const
bool ReduceObjectiveBounds(int64_t lb, int64_t ub)
int64_t SumOfViolations()
Simple summation metric for the constraint and objective violations.
int64_t ObjectiveActivity() const
Returns the objective activity in the current state.
int64_t ObjectiveCoefficient(int var) const
bool IsViolated(int c) const
int64_t Violation(int c) const
absl::Span< const int > ViolatedConstraints() const
absl::Span< const int > VariablesAffectedByLastLinearUpdate() const
void UpdateViolatedList()
absl::Span< const int > ConstraintToVars(int c) const
int NumNonLinearConstraints() const
LinearIncrementalEvaluator * MutableLinearEvaluator()
absl::Span< const int > VarToGeneralConstraints(int var) const
LsEvaluator(const CpModelProto &cp_model, const SatParameters ¶ms)
The cp_model must outlive this class.
int NumInfeasibleConstraints() const
double WeightedViolationDelta(bool linear_only, absl::Span< const double > weights, int var, int64_t delta, absl::Span< int64_t > mutable_solution) const
absl::Span< const int > GeneralConstraintToVars(int general_c) const
void RecomputeViolatedList(bool linear_only)
bool IsObjectiveConstraint(int c) const
const std::vector< int > & last_update_violation_changes() const
int NumLinearConstraints() const
int NumEvaluatorConstraints() const
~NoOverlapBetweenTwoIntervals() override=default
int64_t ComputeViolation(absl::Span< const int64_t > solution) final
std::vector< int > UsedVariables(const CpModelProto &model_proto) const final
int64_t ViolationDelta(int, int64_t, absl::Span< const int64_t > solution_with_new_value) final
NoOverlapBetweenTwoIntervals(int interval_0, int interval_1, const CpModelProto &cp_model)
--— NoOverlapBetweenTwoIntervals --—
In SWIG mode, we don't want anything besides these top-level includes.