OR-Tools  8.0
pseudo_costs.cc
Go to the documentation of this file.
1 // Copyright 2010-2018 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 <cmath>
17 #include <vector>
18 
19 #include "ortools/sat/integer.h"
22 #include "ortools/sat/util.h"
23 
24 namespace operations_research {
25 namespace sat {
26 
28  : integer_trail_(*model->GetOrCreate<IntegerTrail>()),
29  parameters_(*model->GetOrCreate<SatParameters>()) {
30  const int num_vars = integer_trail_.NumIntegerVariables().value();
31  pseudo_costs_.resize(num_vars);
32 }
33 
34 void PseudoCosts::InitializeCosts(double initial_value) {
35  if (pseudo_costs_initialized_) return;
36  VLOG(1) << "Initializing pseudo costs";
37  for (int i = 0; i < pseudo_costs_.size(); ++i) {
38  pseudo_costs_[IntegerVariable(i)].Reset(initial_value);
39  }
40  pseudo_costs_initialized_ = true;
41 }
42 
43 void PseudoCosts::UpdateCostForVar(IntegerVariable var, double new_cost) {
44  if (var >= pseudo_costs_.size()) {
45  // Create space for new variable and its negation.
46  const int new_size = std::max(var, NegationOf(var)).value() + 1;
47  pseudo_costs_.resize(new_size, IncrementalAverage(0.0));
48  }
49  CHECK_LT(var, pseudo_costs_.size());
50  pseudo_costs_[var].AddData(new_cost);
51 }
52 
54  const std::vector<VariableBoundChange>& bound_changes,
55  const IntegerValue obj_bound_improvement) {
56  DCHECK_GE(obj_bound_improvement, 0);
57  if (obj_bound_improvement == IntegerValue(0)) return;
58 
59  for (const VariableBoundChange& decision : bound_changes) {
60  if (integer_trail_.IsCurrentlyIgnored(decision.var)) continue;
61 
62  if (decision.lower_bound_change > IntegerValue(0)) {
63  const double current_pseudo_cost = ToDouble(obj_bound_improvement) /
64  ToDouble(decision.lower_bound_change);
65  // Initialize costs of other variables if not already initialized. This
66  // helps in the 0 reliability threshold case. If the other variables have
67  // 0 pseudo cost, there is a chance that some good variables would never
68  // be branched on. Initializing costs to a positive value doesn't
69  // completely solve that problem but it helps.
70  //
71  // Note that this initial value will be overwritten the first time
72  // UpdateCostForVar() is called.
73  if (!pseudo_costs_initialized_) {
74  InitializeCosts(0.0);
75  }
76  UpdateCostForVar(decision.var, current_pseudo_cost);
77  }
78  }
79 }
80 
82  if (!pseudo_costs_initialized_) return kNoIntegerVariable;
83 
84  const double epsilon = 1e-6;
85 
86  double best_cost = -std::numeric_limits<double>::infinity();
87  IntegerVariable chosen_var = kNoIntegerVariable;
88 
89  for (IntegerVariable positive_var(0); positive_var < pseudo_costs_.size();
90  positive_var += 2) {
91  const IntegerVariable negative_var = NegationOf(positive_var);
92  if (integer_trail_.IsCurrentlyIgnored(positive_var)) continue;
93  const IntegerValue lb = integer_trail_.LowerBound(positive_var);
94  const IntegerValue ub = integer_trail_.UpperBound(positive_var);
95  if (lb >= ub) continue;
96  if (GetRecordings(positive_var) + GetRecordings(negative_var) <
97  parameters_.pseudo_cost_reliability_threshold()) {
98  continue;
99  }
100 
101  // TODO(user): Experiment with different ways to merge the costs.
102  const double current_merged_cost =
103  std::max(GetCost(positive_var), epsilon) *
104  std::max(GetCost(negative_var), epsilon);
105 
106  if (current_merged_cost > best_cost) {
107  chosen_var = positive_var;
108  best_cost = current_merged_cost;
109  }
110  }
111 
112  // Pick the direction with best pseudo cost.
113  if (chosen_var != kNoIntegerVariable &&
114  GetCost(chosen_var) < GetCost(NegationOf(chosen_var))) {
115  chosen_var = NegationOf(chosen_var);
116  }
117  return chosen_var;
118 }
119 
120 std::vector<PseudoCosts::VariableBoundChange> GetBoundChanges(
121  LiteralIndex decision, Model* model) {
122  std::vector<PseudoCosts::VariableBoundChange> bound_changes;
123  if (decision == kNoLiteralIndex) return bound_changes;
124  auto* encoder = model->GetOrCreate<IntegerEncoder>();
125  auto* integer_trail = model->GetOrCreate<IntegerTrail>();
126  // NOTE: We ignore negation of equality decisions.
127  for (const IntegerLiteral l :
128  encoder->GetAllIntegerLiterals(Literal(decision))) {
129  if (l.var == kNoIntegerVariable) continue;
130  if (integer_trail->IsCurrentlyIgnored(l.var)) continue;
131  PseudoCosts::VariableBoundChange var_bound_change;
132  var_bound_change.var = l.var;
133  const IntegerValue current_lb = integer_trail->LowerBound(l.var);
134  var_bound_change.lower_bound_change = Subtract(l.bound, current_lb);
135  bound_changes.push_back(var_bound_change);
136  }
137 
138  return bound_changes;
139 }
140 
141 } // namespace sat
142 } // namespace operations_research
var
IntVar * var
Definition: expr_array.cc:1858
operations_research::sat::IntegerLiteral
Definition: integer.h:164
operations_research::sat::kNoIntegerVariable
const IntegerVariable kNoIntegerVariable(-1)
max
int64 max
Definition: alldiff_cst.cc:139
operations_research::sat::PseudoCosts::PseudoCosts
PseudoCosts(Model *model)
Definition: pseudo_costs.cc:27
operations_research::sat::PseudoCosts::UpdateCost
void UpdateCost(const std::vector< VariableBoundChange > &bound_changes, IntegerValue obj_bound_improvement)
Definition: pseudo_costs.cc:53
operations_research::sat::kNoLiteralIndex
const LiteralIndex kNoLiteralIndex(-1)
operations_research::sat::IntegerTrail::UpperBound
IntegerValue UpperBound(IntegerVariable i) const
Definition: integer.h:1221
pseudo_costs.h
operations_research::sat::PseudoCosts::VariableBoundChange
Definition: pseudo_costs.h:31
operations_research
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
Definition: dense_doubly_linked_list.h:21
operations_research::sat::PseudoCosts::VariableBoundChange::var
IntegerVariable var
Definition: pseudo_costs.h:32
sat_decision.h
operations_research::sat::NegationOf
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
Definition: integer.cc:42
operations_research::sat::IntegerTrail::IsCurrentlyIgnored
bool IsCurrentlyIgnored(IntegerVariable i) const
Definition: integer.h:612
operations_research::sat::IntegerTrail
Definition: integer.h:534
operations_research::sat::Model
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:38
operations_research::sat::Literal
Definition: sat_base.h:64
operations_research::sat::IntegerEncoder
Definition: integer.h:278
operations_research::sat::GetBoundChanges
std::vector< PseudoCosts::VariableBoundChange > GetBoundChanges(LiteralIndex decision, Model *model)
Definition: pseudo_costs.cc:120
sat_parameters.pb.h
operations_research::sat::Subtract
IntegerValue Subtract(IntegerValue a, IntegerValue b)
Definition: integer.h:81
operations_research::sat::IntegerTrail::NumIntegerVariables
IntegerVariable NumIntegerVariables() const
Definition: integer.h:558
operations_research::sat::PseudoCosts::GetCost
double GetCost(IntegerVariable var) const
Definition: pseudo_costs.h:45
operations_research::sat::PseudoCosts::GetBestDecisionVar
IntegerVariable GetBestDecisionVar()
Definition: pseudo_costs.cc:81
operations_research::sat::PseudoCosts::GetRecordings
int GetRecordings(IntegerVariable var) const
Definition: pseudo_costs.h:52
model
GRBmodel * model
Definition: gurobi_interface.cc:195
operations_research::sat::ToDouble
double ToDouble(IntegerValue value)
Definition: integer.h:69
operations_research::sat::IntegerTrail::LowerBound
IntegerValue LowerBound(IntegerVariable i) const
Definition: integer.h:1217
util.h
operations_research::sat::PseudoCosts::VariableBoundChange::lower_bound_change
IntegerValue lower_bound_change
Definition: pseudo_costs.h:33
integer.h