OR-Tools  9.6
statistics.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 <cmath>
18 #include <iomanip>
19 #include <ios>
20 #include <optional>
21 #include <ostream>
22 #include <type_traits>
23 #include <utility>
24 
27 
29 namespace {
30 
31 // Formatter for std::optional<Range> that uses the given width for std::setw().
32 struct OptionalRangeFormatter {
33  OptionalRangeFormatter(const std::optional<Range>& range, const int width)
34  : range(range), width(width) {}
35 
36  const std::optional<Range>& range;
37  const int width;
38 };
39 
40 std::ostream& operator<<(std::ostream& out, const OptionalRangeFormatter& fmt) {
41  if (!fmt.range.has_value()) {
42  out << "no finite values";
43  return out;
44  }
45 
46  out << '[' << std::setw(fmt.width) << fmt.range->first << ", "
47  << std::setw(fmt.width) << fmt.range->second << ']';
48 
49  return out;
50 }
51 
52 // Updates the input optional range with abs(v) if it is finite and non-zero.
53 void UpdateOptionalRange(std::optional<Range>& range, const double v) {
54  if (std::isinf(v) || v == 0.0) {
55  return;
56  }
57 
58  const double abs_v = std::abs(v);
59  if (range.has_value()) {
60  range->first = std::min(range->first, abs_v);
61  range->second = std::max(range->second, abs_v);
62  } else {
63  range = std::make_pair(abs_v, abs_v);
64  }
65 }
66 
67 } // namespace
68 
69 std::ostream& operator<<(std::ostream& out, const ModelRanges& ranges) {
70  const auto last_precision = out.precision(2);
71  const auto last_flags = out.flags();
72  out.setf(std::ios_base::scientific, std::ios_base::floatfield);
73  out.setf(std::ios_base::left, std::ios_base::adjustfield);
74  // Numbers are printed in scientific notation with a precision of 2. Since
75  // they are expected to be positive we can ignore the optional leading minus
76  // sign. We thus expects `d.dde[+-]dd(d)?` (the exponent is at least 2 digits
77  // but double can require 3 digits, with max +308 and min -308). Thus we can
78  // use a width of 9 to align the ranges properly.
79  constexpr int kWidth = 9;
80 
81  out << "Objective terms : "
82  << OptionalRangeFormatter(ranges.objective_terms, kWidth)
83  << "\nVariable bounds : "
84  << OptionalRangeFormatter(ranges.variable_bounds, kWidth)
85  << "\nLinear constraints bounds : "
86  << OptionalRangeFormatter(ranges.linear_constraint_bounds, kWidth)
87  << "\nLinear constraints coeffs : "
88  << OptionalRangeFormatter(ranges.linear_constraint_coefficients, kWidth);
89 
90  out.precision(last_precision);
91  out.flags(last_flags);
92 
93  return out;
94 }
95 
97  ModelRanges ranges;
98  const auto objective = model.ObjectiveAsQuadraticExpression();
99  for (const auto& [_, coeff] : objective.linear_terms()) {
100  UpdateOptionalRange(ranges.objective_terms, coeff);
101  }
102  for (const auto& [_, coeff] : objective.quadratic_terms()) {
103  UpdateOptionalRange(ranges.objective_terms, coeff);
104  }
105  for (const Variable& v : model.Variables()) {
106  UpdateOptionalRange(ranges.variable_bounds, v.lower_bound());
107  UpdateOptionalRange(ranges.variable_bounds, v.upper_bound());
108  }
109  for (const LinearConstraint& c : model.LinearConstraints()) {
110  UpdateOptionalRange(ranges.linear_constraint_bounds, c.lower_bound());
111  UpdateOptionalRange(ranges.linear_constraint_bounds, c.upper_bound());
112  }
113  for (const auto& [_row, _col, coeff] :
114  model.storage()->linear_constraint_matrix()) {
115  UpdateOptionalRange(ranges.linear_constraint_coefficients, coeff);
116  }
117  return ranges;
118 }
119 
120 } // namespace operations_research::math_opt
int64_t max
Definition: alldiff_cst.cc:140
int64_t min
Definition: alldiff_cst.cc:139
GRBmodel * model
ModelRanges ComputeModelRanges(const Model &model)
Definition: statistics.cc:96
std::ostream & operator<<(std::ostream &ostr, const IndicatorConstraint &constraint)
const std::optional< Range > & range
Definition: statistics.cc:36
const int width
Definition: statistics.cc:37
std::optional< Range > linear_constraint_coefficients
Definition: statistics.h:44
std::optional< Range > linear_constraint_bounds
Definition: statistics.h:41
std::optional< Range > variable_bounds
Definition: statistics.h:38
std::optional< Range > objective_terms
Definition: statistics.h:35