OR-Tools  9.6
pseudo_costs.cc
Go to the documentation of this file.
1 // Copyright 2010-2022 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
15 
16 #include <algorithm>
17 #include <limits>
18 #include <vector>
19 
20 #include "ortools/base/logging.h"
22 #include "ortools/sat/integer.h"
23 #include "ortools/sat/model.h"
24 #include "ortools/sat/sat_base.h"
25 #include "ortools/sat/sat_parameters.pb.h"
26 #include "ortools/sat/util.h"
28 
29 namespace operations_research {
30 namespace sat {
31 
33  : parameters_(*model->GetOrCreate<SatParameters>()),
34  integer_trail_(model->GetOrCreate<IntegerTrail>()),
35  encoder_(model->GetOrCreate<IntegerEncoder>()) {
36  const int num_vars = integer_trail_->NumIntegerVariables().value();
37  pseudo_costs_.resize(num_vars);
38 }
39 
40 void PseudoCosts::UpdateCostForVar(IntegerVariable var, double new_cost) {
41  if (var >= pseudo_costs_.size()) {
42  // Create space for new variable and its negation.
43  const int new_size = std::max(var, NegationOf(var)).value() + 1;
44  pseudo_costs_.resize(new_size, IncrementalAverage(0.0));
45  }
46  DCHECK_LT(var, pseudo_costs_.size());
47  pseudo_costs_[var].AddData(new_cost);
48 }
49 
51  const std::vector<VariableBoundChange>& bound_changes,
52  const IntegerValue obj_bound_improvement) {
53  DCHECK_GE(obj_bound_improvement, 0);
54  if (obj_bound_improvement == IntegerValue(0)) return;
55 
56  for (const VariableBoundChange& decision : bound_changes) {
57  if (integer_trail_->IsCurrentlyIgnored(decision.var)) continue;
58  if (decision.lower_bound_change == IntegerValue(0)) continue;
59 
60  const double current_pseudo_cost =
61  ToDouble(obj_bound_improvement) / ToDouble(decision.lower_bound_change);
62  UpdateCostForVar(decision.var, current_pseudo_cost);
63  }
64 }
65 
67  if (pseudo_costs_.empty()) return kNoIntegerVariable;
68 
69  const double epsilon = 1e-6;
70 
71  double best_cost = -std::numeric_limits<double>::infinity();
72  IntegerVariable chosen_var = kNoIntegerVariable;
73 
74  for (IntegerVariable positive_var(0); positive_var < pseudo_costs_.size();
75  positive_var += 2) {
76  const IntegerVariable negative_var = NegationOf(positive_var);
77  if (integer_trail_->IsCurrentlyIgnored(positive_var)) continue;
78  const IntegerValue lb = integer_trail_->LowerBound(positive_var);
79  const IntegerValue ub = integer_trail_->UpperBound(positive_var);
80  if (lb >= ub) continue;
81  if (GetRecordings(positive_var) + GetRecordings(negative_var) <
82  parameters_.pseudo_cost_reliability_threshold()) {
83  continue;
84  }
85 
86  // TODO(user): Experiment with different ways to merge the costs.
87  const double current_merged_cost =
88  std::max(GetCost(positive_var), epsilon) *
89  std::max(GetCost(negative_var), epsilon);
90 
91  if (current_merged_cost > best_cost) {
92  chosen_var = positive_var;
93  best_cost = current_merged_cost;
94  }
95  }
96 
97  // Pick the direction with best pseudo cost.
98  if (chosen_var != kNoIntegerVariable &&
99  GetCost(chosen_var) < GetCost(NegationOf(chosen_var))) {
100  chosen_var = NegationOf(chosen_var);
101  }
102  return chosen_var;
103 }
104 
105 std::vector<PseudoCosts::VariableBoundChange> PseudoCosts::GetBoundChanges(
106  Literal decision) {
107  std::vector<PseudoCosts::VariableBoundChange> bound_changes;
108 
109  for (const IntegerLiteral l : encoder_->GetIntegerLiterals(decision)) {
110  if (integer_trail_->IsCurrentlyIgnored(l.var)) continue;
111  PseudoCosts::VariableBoundChange var_bound_change;
112  var_bound_change.var = l.var;
113  var_bound_change.lower_bound_change =
114  l.bound - integer_trail_->LowerBound(l.var);
115  bound_changes.push_back(var_bound_change);
116  }
117 
118  // NOTE: We ignore literal associated to var != value.
119  for (const auto [var, value] : encoder_->GetEqualityLiterals(decision)) {
120  if (integer_trail_->IsCurrentlyIgnored(var)) continue;
121  {
122  PseudoCosts::VariableBoundChange var_bound_change;
123  var_bound_change.var = var;
124  var_bound_change.lower_bound_change =
125  value - integer_trail_->LowerBound(var);
126  bound_changes.push_back(var_bound_change);
127  }
128 
129  // Also do the negation.
130  {
131  PseudoCosts::VariableBoundChange var_bound_change;
132  var_bound_change.var = NegationOf(var);
133  var_bound_change.lower_bound_change =
134  (-value) - integer_trail_->LowerBound(NegationOf(var));
135  bound_changes.push_back(var_bound_change);
136  }
137  }
138 
139  return bound_changes;
140 }
141 
142 } // namespace sat
143 } // namespace operations_research
int64_t max
Definition: alldiff_cst.cc:140
const InlinedIntegerLiteralVector & GetIntegerLiterals(Literal lit) const
Definition: integer.h:524
const InlinedIntegerValueVector & GetEqualityLiterals(Literal lit) const
Definition: integer.h:533
bool IsCurrentlyIgnored(IntegerVariable i) const
Definition: integer.h:775
IntegerValue UpperBound(IntegerVariable i) const
Definition: integer.h:1561
IntegerValue LowerBound(IntegerVariable i) const
Definition: integer.h:1557
IntegerVariable NumIntegerVariables() const
Definition: integer.h:715
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:42
int GetRecordings(IntegerVariable var) const
Definition: pseudo_costs.h:58
std::vector< VariableBoundChange > GetBoundChanges(Literal decision)
void UpdateCost(const std::vector< VariableBoundChange > &bound_changes, IntegerValue obj_bound_improvement)
Definition: pseudo_costs.cc:50
double GetCost(IntegerVariable var) const
Definition: pseudo_costs.h:51
int64_t value
IntVar * var
Definition: expr_array.cc:1874
GRBmodel * model
const IntegerVariable kNoIntegerVariable(-1)
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
Definition: integer.cc:46
double ToDouble(IntegerValue value)
Definition: integer.h:77
Collection of objects used to extend the Constraint Solver library.