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