OR-Tools  9.3
pseudo_costs.cc
Go to the documentation of this file.
1// Copyright 2010-2021 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
22#include "ortools/sat/integer.h"
23#include "ortools/sat/model.h"
25#include "ortools/sat/sat_parameters.pb.h"
26#include "ortools/sat/util.h"
28
29namespace operations_research {
30namespace sat {
31
33 : integer_trail_(*model->GetOrCreate<IntegerTrail>()),
34 parameters_(*model->GetOrCreate<SatParameters>()) {
35 const int num_vars = integer_trail_.NumIntegerVariables().value();
36 pseudo_costs_.resize(num_vars);
37}
38
39void PseudoCosts::UpdateCostForVar(IntegerVariable var, double new_cost) {
40 if (var >= pseudo_costs_.size()) {
41 // Create space for new variable and its negation.
42 const int new_size = std::max(var, NegationOf(var)).value() + 1;
43 pseudo_costs_.resize(new_size, IncrementalAverage(0.0));
44 }
45 DCHECK_LT(var, pseudo_costs_.size());
46 pseudo_costs_[var].AddData(new_cost);
47}
48
50 const std::vector<VariableBoundChange>& bound_changes,
51 const IntegerValue obj_bound_improvement) {
52 DCHECK_GE(obj_bound_improvement, 0);
53 if (obj_bound_improvement == IntegerValue(0)) return;
54
55 for (const VariableBoundChange& decision : bound_changes) {
56 if (integer_trail_.IsCurrentlyIgnored(decision.var)) continue;
57 if (decision.lower_bound_change == IntegerValue(0)) continue;
58
59 const double current_pseudo_cost =
60 ToDouble(obj_bound_improvement) / ToDouble(decision.lower_bound_change);
61 UpdateCostForVar(decision.var, current_pseudo_cost);
62 }
63}
64
66 if (pseudo_costs_.empty()) return kNoIntegerVariable;
67
68 const double epsilon = 1e-6;
69
70 double best_cost = -std::numeric_limits<double>::infinity();
71 IntegerVariable chosen_var = kNoIntegerVariable;
72
73 for (IntegerVariable positive_var(0); positive_var < pseudo_costs_.size();
74 positive_var += 2) {
75 const IntegerVariable negative_var = NegationOf(positive_var);
76 if (integer_trail_.IsCurrentlyIgnored(positive_var)) continue;
77 const IntegerValue lb = integer_trail_.LowerBound(positive_var);
78 const IntegerValue ub = integer_trail_.UpperBound(positive_var);
79 if (lb >= ub) continue;
80 if (GetRecordings(positive_var) + GetRecordings(negative_var) <
81 parameters_.pseudo_cost_reliability_threshold()) {
82 continue;
83 }
84
85 // TODO(user): Experiment with different ways to merge the costs.
86 const double current_merged_cost =
87 std::max(GetCost(positive_var), epsilon) *
88 std::max(GetCost(negative_var), epsilon);
89
90 if (current_merged_cost > best_cost) {
91 chosen_var = positive_var;
92 best_cost = current_merged_cost;
93 }
94 }
95
96 // Pick the direction with best pseudo cost.
97 if (chosen_var != kNoIntegerVariable &&
98 GetCost(chosen_var) < GetCost(NegationOf(chosen_var))) {
99 chosen_var = NegationOf(chosen_var);
100 }
101 return chosen_var;
102}
103
104std::vector<PseudoCosts::VariableBoundChange> GetBoundChanges(
105 LiteralIndex decision, Model* model) {
106 std::vector<PseudoCosts::VariableBoundChange> bound_changes;
107 if (decision == kNoLiteralIndex) return bound_changes;
108 auto* encoder = model->GetOrCreate<IntegerEncoder>();
109 auto* integer_trail = model->GetOrCreate<IntegerTrail>();
110 // NOTE: We ignore negation of equality decisions.
111 for (const IntegerLiteral l :
112 encoder->GetAllIntegerLiterals(Literal(decision))) {
113 if (l.var == kNoIntegerVariable) continue;
114 if (integer_trail->IsCurrentlyIgnored(l.var)) continue;
115 PseudoCosts::VariableBoundChange var_bound_change;
116 var_bound_change.var = l.var;
117 var_bound_change.lower_bound_change =
118 l.bound - integer_trail->LowerBound(l.var);
119 bound_changes.push_back(var_bound_change);
120 }
121
122 return bound_changes;
123}
124
125} // namespace sat
126} // namespace operations_research
int64_t max
Definition: alldiff_cst.cc:140
#define DCHECK_GE(val1, val2)
Definition: base/logging.h:895
#define DCHECK_LT(val1, val2)
Definition: base/logging.h:894
bool IsCurrentlyIgnored(IntegerVariable i) const
Definition: integer.h:705
IntegerValue UpperBound(IntegerVariable i) const
Definition: integer.h:1449
IntegerValue LowerBound(IntegerVariable i) const
Definition: integer.h:1445
IntegerVariable NumIntegerVariables() const
Definition: integer.h:645
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
void UpdateCost(const std::vector< VariableBoundChange > &bound_changes, IntegerValue obj_bound_improvement)
Definition: pseudo_costs.cc:49
double GetCost(IntegerVariable var) const
Definition: pseudo_costs.h:51
IntVar * var
Definition: expr_array.cc:1874
GRBmodel * model
const LiteralIndex kNoLiteralIndex(-1)
const IntegerVariable kNoIntegerVariable(-1)
std::vector< PseudoCosts::VariableBoundChange > GetBoundChanges(LiteralIndex decision, Model *model)
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
Definition: integer.cc:47
double ToDouble(IntegerValue value)
Definition: integer.h:77
Collection of objects used to extend the Constraint Solver library.