21 #include "absl/container/flat_hash_map.h"
22 #include "absl/strings/str_cat.h"
23 #include "absl/strings/str_format.h"
38 DCHECK(!std::isnan(lower_bound));
39 DCHECK(!std::isnan(upper_bound));
51 lower_bound != upper_bound) {
57 template <
class I,
class T>
59 const size_t size = v.
size();
63 for (I i(0); i < size; ++i) {
64 if (v[i] == 0.0)
continue;
66 sum +=
static_cast<double>(v[i].value());
68 return n == 0.0 ? 0.0 : sum / n;
71 template <
class I,
class T>
73 const size_t size = v.
size();
75 double sigma_square = 0.0;
77 for (I i(0); i < size; ++i) {
78 double sample =
static_cast<double>(v[i].value());
79 if (sample == 0.0)
continue;
80 sigma_square += sample * sample;
84 return n == 0.0 ? 0.0 : sqrt((sigma_square - sigma * sigma / n) / n);
88 template <
class I,
class T>
90 const size_t size = v.
size();
95 T max_index = v[I(0)];
96 for (I i(1); i < size; ++i) {
97 if (max_index < v[i]) {
112 constraint_lower_bounds_(),
113 constraint_upper_bounds_(),
115 objective_coefficients_(),
116 variable_lower_bounds_(),
117 variable_upper_bounds_(),
120 integer_variables_list_(),
123 objective_offset_(0.0),
124 objective_scaling_factor_(1.0),
126 columns_are_known_to_be_clean_(true),
127 transpose_matrix_is_consistent_(true),
128 integer_variables_list_is_consistent_(true),
134 transpose_matrix_.
Clear();
136 constraint_lower_bounds_.
clear();
137 constraint_upper_bounds_.
clear();
138 constraint_names_.
clear();
140 objective_coefficients_.
clear();
141 variable_lower_bounds_.
clear();
142 variable_upper_bounds_.
clear();
143 variable_types_.
clear();
144 integer_variables_list_.clear();
145 variable_names_.
clear();
147 constraint_table_.clear();
148 variable_table_.clear();
151 objective_offset_ = 0.0;
152 objective_scaling_factor_ = 1.0;
153 columns_are_known_to_be_clean_ =
true;
154 transpose_matrix_is_consistent_ =
true;
155 integer_variables_list_is_consistent_ =
true;
162 <<
"New variables can't be added to programs that already have slack "
163 "variables. Consider calling LinearProgram::DeleteSlackVariables() "
164 "before adding new variables to the problem.";
170 transpose_matrix_is_consistent_ =
false;
177 const std::string&
name) {
179 variable_lower_bounds_.
push_back(lower_bound);
180 variable_upper_bounds_.
push_back(upper_bound);
181 variable_types_.
push_back(is_integer_slack_variable
185 transpose_matrix_is_consistent_ =
false;
191 <<
"New constraints can't be added to programs that already have slack "
192 "variables. Consider calling LinearProgram::DeleteSlackVariables() "
193 "before adding new variables to the problem.";
194 const RowIndex
row(constraint_names_.
size());
199 transpose_matrix_is_consistent_ =
false;
204 const absl::flat_hash_map<std::string, ColIndex>::iterator it =
205 variable_table_.find(variable_id);
206 if (it != variable_table_.end()) {
210 variable_names_[
col] = variable_id;
211 variable_table_[variable_id] =
col;
217 const std::string& constraint_id) {
218 const absl::flat_hash_map<std::string, RowIndex>::iterator it =
219 constraint_table_.find(constraint_id);
220 if (it != constraint_table_.end()) {
224 constraint_names_[
row] = constraint_id;
225 constraint_table_[constraint_id] =
row;
231 variable_names_[
col] = std::string(
name);
236 variable_types_[
col] = type;
238 if (var_is_integer != var_was_integer) {
239 integer_variables_list_is_consistent_ =
false;
244 constraint_names_[
row] = std::string(
name);
249 if (dcheck_bounds_) DebugCheckBoundsValid(lower_bound, upper_bound);
251 variable_lower_bounds_[
col] = lower_bound;
252 variable_upper_bounds_[
col] = upper_bound;
254 if (var_is_binary != var_was_binary) {
255 integer_variables_list_is_consistent_ =
false;
259 void LinearProgram::UpdateAllIntegerVariableLists()
const {
260 if (integer_variables_list_is_consistent_)
return;
261 integer_variables_list_.clear();
262 binary_variables_list_.clear();
263 non_binary_variables_list_.clear();
265 for (ColIndex
col(0);
col < num_cols; ++
col) {
267 integer_variables_list_.push_back(
col);
269 binary_variables_list_.push_back(
col);
271 non_binary_variables_list_.push_back(
col);
275 integer_variables_list_is_consistent_ =
true;
279 UpdateAllIntegerVariableLists();
280 return integer_variables_list_;
284 UpdateAllIntegerVariableLists();
285 return binary_variables_list_;
289 UpdateAllIntegerVariableLists();
290 return non_binary_variables_list_;
304 (variable_upper_bounds_[
col] < 2);
309 if (dcheck_bounds_) DebugCheckBoundsValid(lower_bound, upper_bound);
310 ResizeRowsIfNeeded(
row);
311 constraint_lower_bounds_[
row] = lower_bound;
312 constraint_upper_bounds_[
row] = upper_bound;
318 ResizeRowsIfNeeded(
row);
319 columns_are_known_to_be_clean_ =
false;
320 transpose_matrix_is_consistent_ =
false;
326 objective_coefficients_[
col] =
value;
342 maximize_ = maximize;
346 if (columns_are_known_to_be_clean_)
return;
348 columns_are_known_to_be_clean_ =
true;
349 transpose_matrix_is_consistent_ =
false;
353 if (columns_are_known_to_be_clean_)
return true;
354 columns_are_known_to_be_clean_ = matrix_.
IsCleanedUp();
355 return columns_are_known_to_be_clean_;
360 ? absl::StrFormat(
"c%d",
col.value())
361 : variable_names_[
col];
365 return row >= constraint_names_.
size() || constraint_names_[
row].
empty()
366 ? absl::StrFormat(
"r%d",
row.value())
367 : constraint_names_[
row];
371 return variable_types_[
col];
375 if (!transpose_matrix_is_consistent_) {
377 transpose_matrix_is_consistent_ =
true;
381 return transpose_matrix_;
385 if (!transpose_matrix_is_consistent_) {
391 transpose_matrix_is_consistent_ =
false;
392 return &transpose_matrix_;
399 transpose_matrix_is_consistent_ =
true;
403 transpose_matrix_.
Clear();
404 transpose_matrix_is_consistent_ =
false;
412 columns_are_known_to_be_clean_ =
false;
413 transpose_matrix_is_consistent_ =
false;
418 ColIndex
col)
const {
424 return absl::StrFormat(
432 int64 num_non_zeros = 0;
435 for (ColIndex
col(0);
col < objective_coefficients_.
size(); ++
col) {
437 if (
value == 0)
continue;
442 if (num_non_zeros == 0) {
443 return "No objective term. This is a pure feasibility problem.";
445 return absl::StrFormat(
"%d non-zeros, range [%e, %e]", num_non_zeros,
446 min_value, max_value);
455 for (ColIndex
col = ColIndex(0);
col < num_cols; ++
col) {
459 if (lb_error > absolute_tolerance || ub_error > absolute_tolerance) {
473 for (RowIndex
row = RowIndex(0);
row < num_rows; ++
row) {
479 if (lb_error > absolute_tolerance || ub_error > absolute_tolerance) {
492 const Fractional fractionality = fabs(solution[
col] - round(solution[
col]));
493 if (fractionality > absolute_tolerance)
return false;
505 CHECK(solution !=
nullptr);
510 for (RowIndex
row = RowIndex(0);
row < num_rows; ++
row) {
515 (*solution)[slack_variable] = -sum;
531 std::string output = maximize_ ?
"max:" :
"min:";
532 if (objective_offset_ != 0.0) {
536 for (ColIndex
col(0);
col < num_cols; ++
col) {
542 output.append(
";\n");
546 for (RowIndex
row(0);
row < num_rows; ++
row) {
551 if (AreBoundsFreeOrBoxed(lower_bound, upper_bound)) {
556 for (ColIndex
col(0);
col < num_cols; ++
col) {
560 if (AreBoundsFreeOrBoxed(lower_bound, upper_bound)) {
563 }
else if (lower_bound == upper_bound) {
577 for (ColIndex
col(0);
col < num_cols; ++
col) {
580 if (AreBoundsFreeOrBoxed(lower_bound, upper_bound)) {
585 if (AreBoundsFreeOrBoxed(lower_bound, upper_bound)) {
588 }
else if (lower_bound == upper_bound) {
604 if (!integer_variables.empty()) {
606 for (ColIndex
col : integer_variables) {
620 if (!output.empty()) absl::StrAppend(&output,
", ");
622 (variable_values[
col]));
628 return ProblemStatFormatter(
629 "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,"
634 return ProblemStatFormatter(
635 "Number of rows : %d\n"
636 "Number of variables in file : %d\n"
637 "Number of entries (non-zeros) : %d\n"
638 "Number of entries in the objective : %d\n"
639 "Number of entries in the right-hand side : %d\n"
640 "Number of <= constraints : %d\n"
641 "Number of >= constraints : %d\n"
642 "Number of = constraints : %d\n"
643 "Number of range constraints : %d\n"
644 "Number of non-negative variables : %d\n"
645 "Number of boxed variables : %d\n"
646 "Number of free variables : %d\n"
647 "Number of fixed variables : %d\n"
648 "Number of other variables : %d\n"
649 "Number of integer variables : %d\n"
650 "Number of binary variables : %d\n"
651 "Number of non-binary integer variables : %d\n"
652 "Number of continuous variables : %d\n");
656 return NonZeroStatFormatter(
"%.2f%%,%d,%.2f,%.2f,%d,%.2f,%.2f");
660 return NonZeroStatFormatter(
661 "Fill rate : %.2f%%\n"
662 "Entries in row (Max / average / std. dev.) : %d / %.2f / %.2f\n"
663 "Entries in column (Max / average / std. dev.): %d / %.2f / %.2f\n");
667 bool detect_integer_constraints) {
683 detect_integer_constraints);
684 if (detect_integer_constraints) {
689 const RowIndex
row = entry.row();
690 has_integer_slack_variable[
row] =
691 has_integer_slack_variable[
row] && is_integer_variable &&
692 round(entry.coefficient()) == entry.coefficient();
702 slack_variable_index < original_num_variables) {
707 has_integer_slack_variable[
row], -constraint_upper_bounds_[
row],
708 -constraint_lower_bounds_[
row], absl::StrCat(
"s",
row.value()));
713 columns_are_known_to_be_clean_ =
true;
714 transpose_matrix_is_consistent_ =
false;
716 first_slack_variable_ = original_num_variables;
721 return first_slack_variable_;
751 for (RowIndex dual_row(0); dual_row < dual_num_constraints; ++dual_row) {
756 if (lower_bound == upper_bound) {
769 LOG(DFATAL) <<
"PopulateFromDual() was called with a program "
770 <<
"containing free constraints.";
774 for (ColIndex dual_col(0); dual_col < dual_num_variables; ++dual_col) {
785 for (ColIndex dual_col(0); dual_col < dual_num_variables; ++dual_col) {
796 for (ColIndex dual_col(0); dual_col < dual_num_variables; ++dual_col) {
802 const RowIndex dual_row = e.row();
810 for (RowIndex dual_row(0); dual_row < dual_num_constraints; ++dual_row) {
813 if (AreBoundsFreeOrBoxed(lower_bound, upper_bound)) {
822 (*duplicated_rows)[dual_row] =
col;
827 columns_are_known_to_be_clean_ =
true;
828 transpose_matrix_is_consistent_ =
false;
834 if (linear_program.transpose_matrix_is_consistent_) {
835 transpose_matrix_is_consistent_ =
true;
837 linear_program.transpose_matrix_);
839 transpose_matrix_is_consistent_ =
false;
840 transpose_matrix_.
Clear();
843 constraint_lower_bounds_ = linear_program.constraint_lower_bounds_;
844 constraint_upper_bounds_ = linear_program.constraint_upper_bounds_;
845 constraint_names_ = linear_program.constraint_names_;
846 constraint_table_.clear();
848 PopulateNameObjectiveAndVariablesFromLinearProgram(linear_program);
849 first_slack_variable_ = linear_program.first_slack_variable_;
865 inverse_col_permutation);
870 &constraint_lower_bounds_);
872 &constraint_upper_bounds_);
876 &objective_coefficients_);
878 &variable_lower_bounds_);
880 &variable_upper_bounds_);
882 integer_variables_list_is_consistent_ =
false;
888 const RowIndex new_row = row_permutation[old_row];
889 constraint_names_[new_row] = lp.constraint_names_[old_row];
892 for (ColIndex old_col(0); old_col < lp.
num_variables(); ++old_col) {
893 const ColIndex new_col = col_permutation[old_col];
894 variable_names_[new_col] = lp.variable_names_[old_col];
898 maximize_ = lp.maximize_;
899 objective_offset_ = lp.objective_offset_;
900 objective_scaling_factor_ = lp.objective_scaling_factor_;
908 transpose_matrix_is_consistent_ =
false;
909 transpose_matrix_.
Clear();
911 constraint_lower_bounds_.
clear();
912 constraint_upper_bounds_.
clear();
913 constraint_names_.
clear();
914 constraint_table_.clear();
916 PopulateNameObjectiveAndVariablesFromLinearProgram(linear_program);
919 void LinearProgram::PopulateNameObjectiveAndVariablesFromLinearProgram(
921 objective_coefficients_ = linear_program.objective_coefficients_;
922 variable_lower_bounds_ = linear_program.variable_lower_bounds_;
923 variable_upper_bounds_ = linear_program.variable_upper_bounds_;
924 variable_names_ = linear_program.variable_names_;
925 variable_types_ = linear_program.variable_types_;
926 integer_variables_list_is_consistent_ =
927 linear_program.integer_variables_list_is_consistent_;
928 integer_variables_list_ = linear_program.integer_variables_list_;
929 binary_variables_list_ = linear_program.binary_variables_list_;
930 non_binary_variables_list_ = linear_program.non_binary_variables_list_;
931 variable_table_.clear();
933 maximize_ = linear_program.maximize_;
934 objective_offset_ = linear_program.objective_offset_;
935 objective_scaling_factor_ = linear_program.objective_scaling_factor_;
936 columns_are_known_to_be_clean_ =
937 linear_program.columns_are_known_to_be_clean_;
938 name_ = linear_program.name_;
945 const RowIndex num_new_constraints =
coefficients.num_rows();
952 transpose_matrix_is_consistent_ =
false;
953 transpose_matrix_.
Clear();
954 columns_are_known_to_be_clean_ =
false;
957 constraint_lower_bounds_.
insert(constraint_lower_bounds_.
end(),
958 left_hand_sides.
begin(),
959 left_hand_sides.
end());
960 constraint_upper_bounds_.
insert(constraint_upper_bounds_.
end(),
961 right_hand_sides.
begin(),
962 right_hand_sides.
end());
970 bool detect_integer_constraints_for_slack) {
976 const DenseRow& variable_lower_bounds,
977 const DenseRow& variable_upper_bounds) {
982 DenseRow new_lower_bounds(num_vars, 0);
983 DenseRow new_upper_bounds(num_vars, 0);
984 for (ColIndex i(0); i < num_vars; ++i) {
989 if (new_lower_bound > new_upper_bound) {
992 new_lower_bounds[i] = new_lower_bound;
993 new_upper_bounds[i] = new_upper_bound;
995 variable_lower_bounds_.
swap(new_lower_bounds);
996 variable_upper_bounds_.
swap(new_upper_bounds);
1001 matrix_.
Swap(&linear_program->matrix_);
1002 transpose_matrix_.
Swap(&linear_program->transpose_matrix_);
1004 constraint_lower_bounds_.
swap(linear_program->constraint_lower_bounds_);
1005 constraint_upper_bounds_.
swap(linear_program->constraint_upper_bounds_);
1006 constraint_names_.
swap(linear_program->constraint_names_);
1008 objective_coefficients_.
swap(linear_program->objective_coefficients_);
1009 variable_lower_bounds_.
swap(linear_program->variable_lower_bounds_);
1010 variable_upper_bounds_.
swap(linear_program->variable_upper_bounds_);
1011 variable_names_.
swap(linear_program->variable_names_);
1012 variable_types_.
swap(linear_program->variable_types_);
1013 integer_variables_list_.swap(linear_program->integer_variables_list_);
1014 binary_variables_list_.swap(linear_program->binary_variables_list_);
1015 non_binary_variables_list_.swap(linear_program->non_binary_variables_list_);
1017 variable_table_.swap(linear_program->variable_table_);
1018 constraint_table_.swap(linear_program->constraint_table_);
1020 std::swap(maximize_, linear_program->maximize_);
1021 std::swap(objective_offset_, linear_program->objective_offset_);
1022 std::swap(objective_scaling_factor_,
1023 linear_program->objective_scaling_factor_);
1024 std::swap(columns_are_known_to_be_clean_,
1025 linear_program->columns_are_known_to_be_clean_);
1026 std::swap(transpose_matrix_is_consistent_,
1027 linear_program->transpose_matrix_is_consistent_);
1028 std::swap(integer_variables_list_is_consistent_,
1029 linear_program->integer_variables_list_is_consistent_);
1030 name_.swap(linear_program->name_);
1031 std::swap(first_slack_variable_, linear_program->first_slack_variable_);
1035 if (columns_to_delete.
empty())
return;
1036 integer_variables_list_is_consistent_ =
false;
1039 ColIndex new_index(0);
1040 for (ColIndex
col(0);
col < num_cols; ++
col) {
1041 permutation[
col] = new_index;
1042 if (
col >= columns_to_delete.
size() || !columns_to_delete[
col]) {
1043 objective_coefficients_[new_index] = objective_coefficients_[
col];
1044 variable_lower_bounds_[new_index] = variable_lower_bounds_[
col];
1045 variable_upper_bounds_[new_index] = variable_upper_bounds_[
col];
1046 variable_names_[new_index] = variable_names_[
col];
1047 variable_types_[new_index] = variable_types_[
col];
1055 objective_coefficients_.
resize(new_index, 0.0);
1056 variable_lower_bounds_.
resize(new_index, 0.0);
1057 variable_upper_bounds_.
resize(new_index, 0.0);
1059 variable_names_.
resize(new_index,
"");
1062 absl::flat_hash_map<std::string, ColIndex>::iterator it =
1063 variable_table_.begin();
1064 while (it != variable_table_.end()) {
1065 const ColIndex
col = it->second;
1066 if (
col >= columns_to_delete.
size() || !columns_to_delete[
col]) {
1067 it->second = permutation[
col];
1071 variable_table_.erase(it++);
1076 if (transpose_matrix_is_consistent_) {
1087 for (ColIndex slack_variable = first_slack_variable_;
1088 slack_variable < matrix_.
num_cols(); ++slack_variable) {
1094 const RowIndex
row = column.
EntryRow(EntryIndex(0));
1098 -variable_lower_bounds_[slack_variable]);
1099 slack_variables[slack_variable] =
true;
1110 template <
typename FractionalRange>
1111 void UpdateMinAndMaxMagnitude(
const FractionalRange& range,
1116 if (magnitude == 0 || magnitude ==
kInfinity)
continue;
1117 *min_magnitude =
std::min(*min_magnitude, magnitude);
1118 *max_magnitude =
std::max(*max_magnitude, magnitude);
1123 std::vector<Fractional> median;
1125 if (
value == 0.0)
continue;
1126 median.push_back(std::abs(
value));
1128 if (median.empty())
return 1.0;
1129 std::sort(median.begin(), median.end());
1130 return median[median.size() / 2];
1135 int num_non_zeros = 0;
1137 if (
value == 0.0)
continue;
1139 mean += std::abs(
value);
1141 if (num_non_zeros == 0.0)
return 1.0;
1142 return mean /
static_cast<Fractional>(num_non_zeros);
1147 if (min_magnitude > 1.0 && min_magnitude <
kInfinity) {
1148 return min_magnitude;
1149 }
else if (max_magnitude > 0.0 && max_magnitude < 1.0) {
1150 return max_magnitude;
1158 GlopParameters::CostScalingAlgorithm method) {
1165 case GlopParameters::NO_COST_SCALING:
1167 case GlopParameters::CONTAIN_ONE_COST_SCALING:
1168 cost_scaling_factor =
1169 ComputeDivisorSoThatRangeContainsOne(min_magnitude, max_magnitude);
1171 case GlopParameters::MEAN_COST_SCALING:
1174 case GlopParameters::MEDIAN_COST_SCALING:
1178 if (cost_scaling_factor != 1.0) {
1187 VLOG(1) <<
"Objective magnitude range is [" << min_magnitude <<
", "
1188 << max_magnitude <<
"] (dividing by " << cost_scaling_factor <<
").";
1189 return cost_scaling_factor;
1204 ComputeDivisorSoThatRangeContainsOne(min_magnitude, max_magnitude);
1205 if (bound_scaling_factor != 1.0) {
1207 bound_scaling_factor);
1221 VLOG(1) <<
"Bounds magnitude range is [" << min_magnitude <<
", "
1222 << max_magnitude <<
"] (dividing bounds by " << bound_scaling_factor
1224 return bound_scaling_factor;
1228 if (rows_to_delete.
empty())
return;
1234 RowIndex new_index(0);
1235 for (RowIndex
row(0);
row < num_rows; ++
row) {
1236 if (
row >= rows_to_delete.
size() || !rows_to_delete[
row]) {
1237 constraint_lower_bounds_[new_index] = constraint_lower_bounds_[
row];
1238 constraint_upper_bounds_[new_index] = constraint_upper_bounds_[
row];
1239 constraint_names_[new_index].
swap(constraint_names_[
row]);
1240 permutation[
row] = new_index;
1246 constraint_lower_bounds_.
resize(new_index, 0.0);
1247 constraint_upper_bounds_.
resize(new_index, 0.0);
1248 constraint_names_.
resize(new_index,
"");
1254 absl::flat_hash_map<std::string, RowIndex>::iterator it =
1255 constraint_table_.begin();
1256 while (it != constraint_table_.end()) {
1257 const RowIndex
row = it->second;
1259 it->second = permutation[
row];
1263 constraint_table_.erase(it++);
1268 if (transpose_matrix_is_consistent_) {
1275 if (!
IsFinite(objective_offset_))
return false;
1276 if (!
IsFinite(objective_scaling_factor_))
return false;
1277 if (objective_scaling_factor_ == 0.0)
return false;
1279 for (ColIndex
col(0);
col < num_cols; ++
col) {
1288 if (!
IsFinite(e.coefficient()))
return false;
1291 if (constraint_upper_bounds_.
size() != constraint_lower_bounds_.
size()) {
1294 for (RowIndex
row(0);
row < constraint_lower_bounds_.
size(); ++
row) {
1303 std::string LinearProgram::ProblemStatFormatter(
1304 const absl::string_view format)
const {
1305 int num_objective_non_zeros = 0;
1306 int num_non_negative_variables = 0;
1307 int num_boxed_variables = 0;
1308 int num_free_variables = 0;
1309 int num_fixed_variables = 0;
1310 int num_other_variables = 0;
1312 for (ColIndex
col(0);
col < num_cols; ++
col) {
1314 ++num_objective_non_zeros;
1319 const bool lower_bounded = (lower_bound != -
kInfinity);
1320 const bool upper_bounded = (upper_bound !=
kInfinity);
1322 if (!lower_bounded && !upper_bounded) {
1323 ++num_free_variables;
1324 }
else if (lower_bound == 0.0 && !upper_bounded) {
1325 ++num_non_negative_variables;
1326 }
else if (!upper_bounded || !lower_bounded) {
1327 ++num_other_variables;
1328 }
else if (lower_bound == upper_bound) {
1329 ++num_fixed_variables;
1331 ++num_boxed_variables;
1335 int num_range_constraints = 0;
1336 int num_less_than_constraints = 0;
1337 int num_greater_than_constraints = 0;
1338 int num_equal_constraints = 0;
1339 int num_rhs_non_zeros = 0;
1341 for (RowIndex
row(0);
row < num_rows; ++
row) {
1344 if (AreBoundsFreeOrBoxed(lower_bound, upper_bound)) {
1347 ++num_range_constraints;
1350 if (lower_bound == upper_bound) {
1351 ++num_equal_constraints;
1352 if (lower_bound != 0) {
1353 ++num_rhs_non_zeros;
1358 ++num_less_than_constraints;
1359 if (upper_bound != 0) {
1360 ++num_rhs_non_zeros;
1365 ++num_greater_than_constraints;
1366 if (lower_bound != 0) {
1367 ++num_rhs_non_zeros;
1371 LOG(DFATAL) <<
"There is a bug since all possible cases for the row bounds "
1372 "should have been accounted for. row="
1379 const int num_continuous_variables =
1381 auto format_runtime =
1382 absl::ParsedFormat<
'd',
'd',
'd',
'd',
'd',
'd',
'd',
'd',
'd',
'd',
'd',
1383 'd',
'd',
'd',
'd',
'd',
'd',
'd'>::New(format);
1384 CHECK(format_runtime);
1385 return absl::StrFormat(
1388 num_objective_non_zeros, num_rhs_non_zeros, num_less_than_constraints,
1389 num_greater_than_constraints, num_equal_constraints,
1390 num_range_constraints, num_non_negative_variables, num_boxed_variables,
1391 num_free_variables, num_fixed_variables, num_other_variables,
1392 num_integer_variables, num_binary_variables, num_non_binary_variables,
1393 num_continuous_variables);
1396 std::string LinearProgram::NonZeroStatFormatter(
1397 const absl::string_view format)
const {
1398 StrictITIVector<RowIndex, EntryIndex> num_entries_in_row(
num_constraints(),
1400 StrictITIVector<ColIndex, EntryIndex> num_entries_in_column(
num_variables(),
1404 for (ColIndex
col(0);
col < num_cols; ++
col) {
1407 num_entries_in_column[
col] = sparse_column.num_entries();
1409 ++num_entries_in_row[e.row()];
1417 const double fill_rate = 100.0 *
static_cast<double>(
num_entries.value()) /
1418 static_cast<double>(height * width);
1420 auto format_runtime =
1421 absl::ParsedFormat<'f', 'd', 'f', 'f', 'd', 'f', 'f'>::New(format);
1422 return absl::StrFormat(
1423 *format_runtime, fill_rate, GetMaxElement(num_entries_in_row).
value(),
1424 Average(num_entries_in_row), StandardDeviation(num_entries_in_row),
1425 GetMaxElement(num_entries_in_column).
value(),
1426 Average(num_entries_in_column), StandardDeviation(num_entries_in_column));
1429 void LinearProgram::ResizeRowsIfNeeded(RowIndex
row) {
1432 transpose_matrix_is_consistent_ =
false;
1441 for (RowIndex constraint(0); constraint <
num_constraints(); ++constraint) {
1442 if (constraint_lower_bounds_[constraint] != 0.0 ||
1443 constraint_upper_bounds_[constraint] != 0.0) {
1447 const ColIndex num_slack_variables =
1460 VLOG(1) <<
"Bounds of variable " <<
col.value() <<
" are non-integer ("
1461 << variable_lower_bounds_[
col] <<
", "
1462 << variable_upper_bounds_[
col] <<
").";
1476 bool integer_constraint =
true;
1479 integer_constraint =
false;
1483 integer_constraint =
false;
1487 if (integer_constraint) {
1494 VLOG(1) <<
"Bounds of constraint " <<
row.value()
1495 <<
" are non-integer (" << constraint_lower_bounds_[
row] <<
", "
1496 << constraint_upper_bounds_[
row] <<
").";
1510 absl::StrAppendFormat(&s,
"\n Var #%d: %s %g",
col.value(),
1514 s +=
"\n------------------------------";
1516 absl::StrAppendFormat(&s,
"\n Constraint #%d: %s %g",
row.value(),