22 #include "absl/container/flat_hash_map.h" 23 #include "absl/strings/str_cat.h" 24 #include "absl/strings/str_format.h" 59 template <
class I,
class T>
61 const size_t size = v.
size();
65 for (I i(0); i < size; ++i) {
66 if (v[i] == 0.0)
continue;
68 sum += static_cast<double>(v[i].
value());
70 return n == 0.0 ? 0.0 : sum / n;
73 template <
class I,
class T>
75 const size_t size = v.
size();
77 double sigma_square = 0.0;
79 for (I i(0); i < size; ++i) {
80 double sample = static_cast<double>(v[i].
value());
81 if (sample == 0.0)
continue;
82 sigma_square += sample * sample;
86 return n == 0.0 ? 0.0 : sqrt((sigma_square - sigma * sigma / n) / n);
90 template <
class I,
class T>
92 const size_t size = v.
size();
97 T max_index = v[I(0)];
98 for (I i(1); i < size; ++i) {
99 if (max_index < v[i]) {
114 constraint_lower_bounds_(),
115 constraint_upper_bounds_(),
117 objective_coefficients_(),
118 variable_lower_bounds_(),
119 variable_upper_bounds_(),
122 integer_variables_list_(),
125 objective_offset_(0.0),
126 objective_scaling_factor_(1.0),
128 columns_are_known_to_be_clean_(true),
129 transpose_matrix_is_consistent_(true),
130 integer_variables_list_is_consistent_(true),
136 transpose_matrix_.
Clear();
138 constraint_lower_bounds_.
clear();
139 constraint_upper_bounds_.
clear();
140 constraint_names_.
clear();
142 objective_coefficients_.
clear();
143 variable_lower_bounds_.
clear();
144 variable_upper_bounds_.
clear();
145 variable_types_.
clear();
146 integer_variables_list_.clear();
147 variable_names_.
clear();
149 constraint_table_.clear();
150 variable_table_.clear();
153 objective_offset_ = 0.0;
154 objective_scaling_factor_ = 1.0;
155 columns_are_known_to_be_clean_ =
true;
156 transpose_matrix_is_consistent_ =
true;
157 integer_variables_list_is_consistent_ =
true;
164 <<
"New variables can't be added to programs that already have slack " 165 "variables. Consider calling LinearProgram::DeleteSlackVariables() " 166 "before adding new variables to the problem.";
172 transpose_matrix_is_consistent_ =
false;
179 const std::string&
name) {
183 variable_types_.
push_back(is_integer_slack_variable
187 transpose_matrix_is_consistent_ =
false;
193 <<
"New constraints can't be added to programs that already have slack " 194 "variables. Consider calling LinearProgram::DeleteSlackVariables() " 195 "before adding new variables to the problem.";
196 const RowIndex
row(constraint_names_.
size());
201 transpose_matrix_is_consistent_ =
false;
206 const absl::flat_hash_map<std::string, ColIndex>::iterator it =
207 variable_table_.find(variable_id);
208 if (it != variable_table_.end()) {
212 variable_names_[
col] = variable_id;
213 variable_table_[variable_id] =
col;
219 const std::string& constraint_id) {
220 const absl::flat_hash_map<std::string, RowIndex>::iterator it =
221 constraint_table_.find(constraint_id);
222 if (it != constraint_table_.end()) {
226 constraint_names_[
row] = constraint_id;
227 constraint_table_[constraint_id] =
row;
233 variable_names_[
col] = std::string(
name);
238 variable_types_[
col] = type;
240 if (var_is_integer != var_was_integer) {
241 integer_variables_list_is_consistent_ =
false;
246 constraint_names_[
row] = std::string(
name);
256 if (var_is_binary != var_was_binary) {
257 integer_variables_list_is_consistent_ =
false;
261 void LinearProgram::UpdateAllIntegerVariableLists()
const {
262 if (integer_variables_list_is_consistent_)
return;
263 integer_variables_list_.clear();
264 binary_variables_list_.clear();
265 non_binary_variables_list_.clear();
267 for (ColIndex
col(0);
col < num_cols; ++
col) {
269 integer_variables_list_.push_back(
col);
271 binary_variables_list_.push_back(
col);
273 non_binary_variables_list_.push_back(
col);
277 integer_variables_list_is_consistent_ =
true;
281 UpdateAllIntegerVariableLists();
282 return integer_variables_list_;
286 UpdateAllIntegerVariableLists();
287 return binary_variables_list_;
291 UpdateAllIntegerVariableLists();
292 return non_binary_variables_list_;
306 (variable_upper_bounds_[
col] < 2);
312 ResizeRowsIfNeeded(
row);
320 ResizeRowsIfNeeded(
row);
321 columns_are_known_to_be_clean_ =
false;
322 transpose_matrix_is_consistent_ =
false;
328 objective_coefficients_[
col] =
value;
344 maximize_ = maximize;
348 if (columns_are_known_to_be_clean_)
return;
350 columns_are_known_to_be_clean_ =
true;
351 transpose_matrix_is_consistent_ =
false;
355 if (columns_are_known_to_be_clean_)
return true;
356 columns_are_known_to_be_clean_ = matrix_.
IsCleanedUp();
357 return columns_are_known_to_be_clean_;
362 ? absl::StrFormat(
"c%d",
col.value())
363 : variable_names_[
col];
367 return row >= constraint_names_.
size() || constraint_names_[
row].
empty()
368 ? absl::StrFormat(
"r%d",
row.value())
369 : constraint_names_[
row];
373 return variable_types_[
col];
377 if (!transpose_matrix_is_consistent_) {
379 transpose_matrix_is_consistent_ =
true;
383 return transpose_matrix_;
387 if (!transpose_matrix_is_consistent_) {
393 transpose_matrix_is_consistent_ =
false;
394 return &transpose_matrix_;
401 transpose_matrix_is_consistent_ =
true;
405 transpose_matrix_.
Clear();
406 transpose_matrix_is_consistent_ =
false;
414 columns_are_known_to_be_clean_ =
false;
415 transpose_matrix_is_consistent_ =
false;
420 ColIndex
col)
const {
429 return absl::StrFormat(
430 "%d rows, %d columns, %d entries with magnitude in [%e, %e]",
439 template <
typename FractionalValues>
440 void UpdateStats(
const FractionalValues& values, int64_t* num_non_zeros,
444 *min_value =
std::min(*min_value, v);
445 *max_value =
std::max(*max_value, v);
453 int64_t num_non_zeros = 0;
456 UpdateStats(objective_coefficients_, &num_non_zeros, &min_value, &max_value);
457 if (num_non_zeros == 0) {
458 return "No objective term. This is a pure feasibility problem.";
460 return absl::StrFormat(
"%d non-zeros, range [%e, %e]", num_non_zeros,
461 min_value, max_value);
466 int64_t num_non_zeros = 0;
469 UpdateStats(variable_lower_bounds_, &num_non_zeros, &min_value, &max_value);
470 UpdateStats(variable_upper_bounds_, &num_non_zeros, &min_value, &max_value);
471 UpdateStats(constraint_lower_bounds_, &num_non_zeros, &min_value, &max_value);
472 UpdateStats(constraint_upper_bounds_, &num_non_zeros, &min_value, &max_value);
473 if (num_non_zeros == 0) {
474 return "All variables/constraints bounds are zero or +/- infinity.";
476 return absl::StrFormat(
"%d non-zeros, range [%e, %e]", num_non_zeros,
477 min_value, max_value);
486 for (ColIndex
col = ColIndex(0);
col < num_cols; ++
col) {
490 if (lb_error > absolute_tolerance || ub_error > absolute_tolerance) {
504 for (RowIndex
row = RowIndex(0);
row < num_rows; ++
row) {
510 if (lb_error > absolute_tolerance || ub_error > absolute_tolerance) {
523 const Fractional fractionality = fabs(solution[
col] - round(solution[
col]));
524 if (fractionality > absolute_tolerance)
return false;
536 CHECK(solution !=
nullptr);
541 for (RowIndex
row = RowIndex(0);
row < num_rows; ++
row) {
546 (*solution)[slack_variable] = -sum;
562 std::string output = maximize_ ?
"max:" :
"min:";
563 if (objective_offset_ != 0.0) {
567 for (ColIndex
col(0);
col < num_cols; ++
col) {
573 output.append(
";\n");
577 for (RowIndex
row(0);
row < num_rows; ++
row) {
587 for (ColIndex
col(0);
col < num_cols; ++
col) {
608 for (ColIndex
col(0);
col < num_cols; ++
col) {
635 if (!integer_variables.empty()) {
637 for (ColIndex
col : integer_variables) {
651 if (!output.empty()) absl::StrAppend(&output,
", ");
653 (variable_values[
col]));
659 return ProblemStatFormatter(
660 "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d," 665 return ProblemStatFormatter(
666 "Number of rows : %d\n" 667 "Number of variables in file : %d\n" 668 "Number of entries (non-zeros) : %d\n" 669 "Number of entries in the objective : %d\n" 670 "Number of entries in the right-hand side : %d\n" 671 "Number of <= constraints : %d\n" 672 "Number of >= constraints : %d\n" 673 "Number of = constraints : %d\n" 674 "Number of range constraints : %d\n" 675 "Number of non-negative variables : %d\n" 676 "Number of boxed variables : %d\n" 677 "Number of free variables : %d\n" 678 "Number of fixed variables : %d\n" 679 "Number of other variables : %d\n" 680 "Number of integer variables : %d\n" 681 "Number of binary variables : %d\n" 682 "Number of non-binary integer variables : %d\n" 683 "Number of continuous variables : %d\n");
687 return NonZeroStatFormatter(
"%.2f%%,%d,%.2f,%.2f,%d,%.2f,%.2f");
691 return NonZeroStatFormatter(
692 "Fill rate : %.2f%%\n" 693 "Entries in row (Max / average / std. dev.) : %d / %.2f / %.2f\n" 694 "Entries in column (Max / average / std. dev.): %d / %.2f / %.2f\n");
698 bool detect_integer_constraints) {
714 detect_integer_constraints);
715 if (detect_integer_constraints) {
720 const RowIndex
row = entry.row();
721 has_integer_slack_variable[
row] =
722 has_integer_slack_variable[
row] && is_integer_variable &&
723 round(entry.coefficient()) == entry.coefficient();
733 slack_variable_index < original_num_variables) {
738 has_integer_slack_variable[
row], -constraint_upper_bounds_[
row],
739 -constraint_lower_bounds_[
row], absl::StrCat(
"s",
row.value()));
744 columns_are_known_to_be_clean_ =
true;
745 transpose_matrix_is_consistent_ =
false;
747 first_slack_variable_ = original_num_variables;
752 return first_slack_variable_;
782 for (RowIndex dual_row(0); dual_row < dual_num_constraints; ++dual_row) {
800 LOG(DFATAL) <<
"PopulateFromDual() was called with a program " 801 <<
"containing free constraints.";
805 for (ColIndex dual_col(0); dual_col < dual_num_variables; ++dual_col) {
816 for (ColIndex dual_col(0); dual_col < dual_num_variables; ++dual_col) {
827 for (ColIndex dual_col(0); dual_col < dual_num_variables; ++dual_col) {
833 const RowIndex dual_row = e.row();
841 for (RowIndex dual_row(0); dual_row < dual_num_constraints; ++dual_row) {
853 (*duplicated_rows)[dual_row] =
col;
858 columns_are_known_to_be_clean_ =
true;
859 transpose_matrix_is_consistent_ =
false;
865 if (linear_program.transpose_matrix_is_consistent_) {
866 transpose_matrix_is_consistent_ =
true;
868 linear_program.transpose_matrix_);
870 transpose_matrix_is_consistent_ =
false;
871 transpose_matrix_.
Clear();
874 constraint_lower_bounds_ = linear_program.constraint_lower_bounds_;
875 constraint_upper_bounds_ = linear_program.constraint_upper_bounds_;
876 constraint_names_ = linear_program.constraint_names_;
877 constraint_table_.clear();
879 PopulateNameObjectiveAndVariablesFromLinearProgram(linear_program);
880 first_slack_variable_ = linear_program.first_slack_variable_;
896 inverse_col_permutation);
901 &constraint_lower_bounds_);
903 &constraint_upper_bounds_);
907 &objective_coefficients_);
909 &variable_lower_bounds_);
911 &variable_upper_bounds_);
913 integer_variables_list_is_consistent_ =
false;
919 const RowIndex new_row = row_permutation[old_row];
920 constraint_names_[new_row] = lp.constraint_names_[old_row];
923 for (ColIndex old_col(0); old_col < lp.
num_variables(); ++old_col) {
924 const ColIndex new_col = col_permutation[old_col];
925 variable_names_[new_col] = lp.variable_names_[old_col];
929 maximize_ = lp.maximize_;
930 objective_offset_ = lp.objective_offset_;
931 objective_scaling_factor_ = lp.objective_scaling_factor_;
939 transpose_matrix_is_consistent_ =
false;
940 transpose_matrix_.
Clear();
942 constraint_lower_bounds_.
clear();
943 constraint_upper_bounds_.
clear();
944 constraint_names_.
clear();
945 constraint_table_.clear();
947 PopulateNameObjectiveAndVariablesFromLinearProgram(linear_program);
950 void LinearProgram::PopulateNameObjectiveAndVariablesFromLinearProgram(
952 objective_coefficients_ = linear_program.objective_coefficients_;
953 variable_lower_bounds_ = linear_program.variable_lower_bounds_;
954 variable_upper_bounds_ = linear_program.variable_upper_bounds_;
955 variable_names_ = linear_program.variable_names_;
956 variable_types_ = linear_program.variable_types_;
957 integer_variables_list_is_consistent_ =
958 linear_program.integer_variables_list_is_consistent_;
959 integer_variables_list_ = linear_program.integer_variables_list_;
960 binary_variables_list_ = linear_program.binary_variables_list_;
961 non_binary_variables_list_ = linear_program.non_binary_variables_list_;
962 variable_table_.clear();
964 maximize_ = linear_program.maximize_;
965 objective_offset_ = linear_program.objective_offset_;
966 objective_scaling_factor_ = linear_program.objective_scaling_factor_;
967 columns_are_known_to_be_clean_ =
968 linear_program.columns_are_known_to_be_clean_;
969 name_ = linear_program.name_;
976 const RowIndex num_new_constraints =
coefficients.num_rows();
983 transpose_matrix_is_consistent_ =
false;
984 transpose_matrix_.
Clear();
985 columns_are_known_to_be_clean_ =
false;
988 constraint_lower_bounds_.
insert(constraint_lower_bounds_.
end(),
989 left_hand_sides.
begin(),
990 left_hand_sides.
end());
991 constraint_upper_bounds_.
insert(constraint_upper_bounds_.
end(),
992 right_hand_sides.
begin(),
993 right_hand_sides.
end());
1001 bool detect_integer_constraints_for_slack) {
1007 const DenseRow& variable_lower_bounds,
1008 const DenseRow& variable_upper_bounds) {
1013 DenseRow new_lower_bounds(num_vars, 0);
1014 DenseRow new_upper_bounds(num_vars, 0);
1015 for (ColIndex i(0); i < num_vars; ++i) {
1020 if (new_lower_bound > new_upper_bound) {
1023 new_lower_bounds[i] = new_lower_bound;
1024 new_upper_bounds[i] = new_upper_bound;
1026 variable_lower_bounds_.
swap(new_lower_bounds);
1027 variable_upper_bounds_.
swap(new_upper_bounds);
1032 matrix_.
Swap(&linear_program->matrix_);
1033 transpose_matrix_.
Swap(&linear_program->transpose_matrix_);
1035 constraint_lower_bounds_.
swap(linear_program->constraint_lower_bounds_);
1036 constraint_upper_bounds_.
swap(linear_program->constraint_upper_bounds_);
1037 constraint_names_.
swap(linear_program->constraint_names_);
1039 objective_coefficients_.
swap(linear_program->objective_coefficients_);
1040 variable_lower_bounds_.
swap(linear_program->variable_lower_bounds_);
1041 variable_upper_bounds_.
swap(linear_program->variable_upper_bounds_);
1042 variable_names_.
swap(linear_program->variable_names_);
1043 variable_types_.
swap(linear_program->variable_types_);
1044 integer_variables_list_.swap(linear_program->integer_variables_list_);
1045 binary_variables_list_.swap(linear_program->binary_variables_list_);
1046 non_binary_variables_list_.swap(linear_program->non_binary_variables_list_);
1048 variable_table_.swap(linear_program->variable_table_);
1049 constraint_table_.swap(linear_program->constraint_table_);
1051 std::swap(maximize_, linear_program->maximize_);
1052 std::swap(objective_offset_, linear_program->objective_offset_);
1054 linear_program->objective_scaling_factor_);
1055 std::swap(columns_are_known_to_be_clean_,
1056 linear_program->columns_are_known_to_be_clean_);
1057 std::swap(transpose_matrix_is_consistent_,
1058 linear_program->transpose_matrix_is_consistent_);
1059 std::swap(integer_variables_list_is_consistent_,
1060 linear_program->integer_variables_list_is_consistent_);
1061 name_.swap(linear_program->name_);
1062 std::swap(first_slack_variable_, linear_program->first_slack_variable_);
1066 if (columns_to_delete.
empty())
return;
1067 integer_variables_list_is_consistent_ =
false;
1070 ColIndex new_index(0);
1071 for (ColIndex
col(0);
col < num_cols; ++
col) {
1072 permutation[
col] = new_index;
1073 if (
col >= columns_to_delete.
size() || !columns_to_delete[
col]) {
1074 objective_coefficients_[new_index] = objective_coefficients_[
col];
1075 variable_lower_bounds_[new_index] = variable_lower_bounds_[
col];
1076 variable_upper_bounds_[new_index] = variable_upper_bounds_[
col];
1077 variable_names_[new_index] = variable_names_[
col];
1078 variable_types_[new_index] = variable_types_[
col];
1086 objective_coefficients_.
resize(new_index, 0.0);
1087 variable_lower_bounds_.
resize(new_index, 0.0);
1088 variable_upper_bounds_.
resize(new_index, 0.0);
1090 variable_names_.
resize(new_index,
"");
1093 absl::flat_hash_map<std::string, ColIndex>::iterator it =
1094 variable_table_.begin();
1095 while (it != variable_table_.end()) {
1096 const ColIndex
col = it->second;
1097 if (
col >= columns_to_delete.
size() || !columns_to_delete[
col]) {
1098 it->second = permutation[
col];
1102 variable_table_.erase(it++);
1107 if (transpose_matrix_is_consistent_) {
1110 reinterpret_cast<const RowPermutation&>(permutation));
1118 for (ColIndex slack_variable = first_slack_variable_;
1119 slack_variable < matrix_.
num_cols(); ++slack_variable) {
1125 const RowIndex
row = column.
EntryRow(EntryIndex(0));
1129 -variable_lower_bounds_[slack_variable]);
1130 slack_variables[slack_variable] =
true;
1141 template <
typename FractionalRange>
1142 void UpdateMinAndMaxMagnitude(
const FractionalRange& range,
1147 if (magnitude == 0 || magnitude ==
kInfinity)
continue;
1148 *min_magnitude =
std::min(*min_magnitude, magnitude);
1149 *max_magnitude =
std::max(*max_magnitude, magnitude);
1154 std::vector<Fractional> median;
1156 if (
value == 0.0)
continue;
1157 median.push_back(std::abs(
value));
1159 if (median.empty())
return 1.0;
1160 std::sort(median.begin(), median.end());
1161 return median[median.size() / 2];
1166 int num_non_zeros = 0;
1168 if (
value == 0.0)
continue;
1170 mean += std::abs(
value);
1172 if (num_non_zeros == 0.0)
return 1.0;
1173 return mean / static_cast<Fractional>(num_non_zeros);
1178 if (min_magnitude > 1.0 && min_magnitude <
kInfinity) {
1179 return min_magnitude;
1180 }
else if (max_magnitude > 0.0 && max_magnitude < 1.0) {
1181 return max_magnitude;
1199 cost_scaling_factor =
1200 ComputeDivisorSoThatRangeContainsOne(min_magnitude, max_magnitude);
1209 if (cost_scaling_factor != 1.0) {
1218 VLOG(1) <<
"Objective magnitude range is [" << min_magnitude <<
", " 1219 << max_magnitude <<
"] (dividing by " << cost_scaling_factor <<
").";
1220 return cost_scaling_factor;
1235 ComputeDivisorSoThatRangeContainsOne(min_magnitude, max_magnitude);
1236 if (bound_scaling_factor != 1.0) {
1238 bound_scaling_factor);
1252 VLOG(1) <<
"Bounds magnitude range is [" << min_magnitude <<
", " 1253 << max_magnitude <<
"] (dividing bounds by " << bound_scaling_factor
1255 return bound_scaling_factor;
1259 if (rows_to_delete.
empty())
return;
1265 RowIndex new_index(0);
1266 for (RowIndex
row(0);
row < num_rows; ++
row) {
1267 if (
row >= rows_to_delete.
size() || !rows_to_delete[
row]) {
1268 constraint_lower_bounds_[new_index] = constraint_lower_bounds_[
row];
1269 constraint_upper_bounds_[new_index] = constraint_upper_bounds_[
row];
1270 constraint_names_[new_index].
swap(constraint_names_[
row]);
1271 permutation[
row] = new_index;
1277 constraint_lower_bounds_.
resize(new_index, 0.0);
1278 constraint_upper_bounds_.
resize(new_index, 0.0);
1279 constraint_names_.
resize(new_index,
"");
1285 absl::flat_hash_map<std::string, RowIndex>::iterator it =
1286 constraint_table_.begin();
1287 while (it != constraint_table_.end()) {
1288 const RowIndex
row = it->second;
1290 it->second = permutation[
row];
1294 constraint_table_.erase(it++);
1299 if (transpose_matrix_is_consistent_) {
1301 reinterpret_cast<const DenseBooleanRow&>(rows_to_delete));
1306 if (!
IsFinite(objective_offset_))
return false;
1307 if (!
IsFinite(objective_scaling_factor_))
return false;
1308 if (objective_scaling_factor_ == 0.0)
return false;
1310 for (ColIndex
col(0);
col < num_cols; ++
col) {
1319 if (!
IsFinite(e.coefficient()))
return false;
1322 if (constraint_upper_bounds_.
size() != constraint_lower_bounds_.
size()) {
1325 for (RowIndex
row(0);
row < constraint_lower_bounds_.
size(); ++
row) {
1334 std::string LinearProgram::ProblemStatFormatter(
1335 const absl::string_view format)
const {
1336 int num_objective_non_zeros = 0;
1337 int num_non_negative_variables = 0;
1338 int num_boxed_variables = 0;
1339 int num_free_variables = 0;
1340 int num_fixed_variables = 0;
1341 int num_other_variables = 0;
1343 for (ColIndex
col(0);
col < num_cols; ++
col) {
1345 ++num_objective_non_zeros;
1353 if (!lower_bounded && !upper_bounded) {
1354 ++num_free_variables;
1355 }
else if (
lower_bound == 0.0 && !upper_bounded) {
1356 ++num_non_negative_variables;
1357 }
else if (!upper_bounded || !lower_bounded) {
1358 ++num_other_variables;
1360 ++num_fixed_variables;
1362 ++num_boxed_variables;
1366 int num_range_constraints = 0;
1367 int num_less_than_constraints = 0;
1368 int num_greater_than_constraints = 0;
1369 int num_equal_constraints = 0;
1370 int num_rhs_non_zeros = 0;
1372 for (RowIndex
row(0);
row < num_rows; ++
row) {
1378 ++num_range_constraints;
1382 ++num_equal_constraints;
1384 ++num_rhs_non_zeros;
1389 ++num_less_than_constraints;
1391 ++num_rhs_non_zeros;
1396 ++num_greater_than_constraints;
1398 ++num_rhs_non_zeros;
1402 LOG(DFATAL) <<
"There is a bug since all possible cases for the row bounds " 1403 "should have been accounted for. row=" 1410 const int num_continuous_variables =
1412 auto format_runtime =
1413 absl::ParsedFormat<
'd',
'd',
'd',
'd',
'd',
'd',
'd',
'd',
'd',
'd',
'd',
1414 'd',
'd',
'd',
'd',
'd',
'd',
'd'>::New(format);
1415 CHECK(format_runtime);
1416 return absl::StrFormat(
1419 num_objective_non_zeros, num_rhs_non_zeros, num_less_than_constraints,
1420 num_greater_than_constraints, num_equal_constraints,
1421 num_range_constraints, num_non_negative_variables, num_boxed_variables,
1422 num_free_variables, num_fixed_variables, num_other_variables,
1423 num_integer_variables, num_binary_variables, num_non_binary_variables,
1424 num_continuous_variables);
1427 std::string LinearProgram::NonZeroStatFormatter(
1428 const absl::string_view format)
const {
1429 StrictITIVector<RowIndex, EntryIndex> num_entries_in_row(
num_constraints(),
1431 StrictITIVector<ColIndex, EntryIndex> num_entries_in_column(
num_variables(),
1435 for (ColIndex
col(0);
col < num_cols; ++
col) {
1438 num_entries_in_column[
col] = sparse_column.num_entries();
1440 ++num_entries_in_row[e.row()];
1448 const double fill_rate = 100.0 * static_cast<double>(
num_entries.value()) /
1449 static_cast<double>(height * width);
1451 auto format_runtime =
1452 absl::ParsedFormat<'f', 'd', 'f', 'f', 'd', 'f', 'f'>::New(format);
1453 return absl::StrFormat(
1454 *format_runtime, fill_rate, GetMaxElement(num_entries_in_row).
value(),
1455 Average(num_entries_in_row), StandardDeviation(num_entries_in_row),
1456 GetMaxElement(num_entries_in_column).
value(),
1457 Average(num_entries_in_column), StandardDeviation(num_entries_in_column));
1460 void LinearProgram::ResizeRowsIfNeeded(RowIndex
row) {
1463 transpose_matrix_is_consistent_ =
false;
1472 for (RowIndex constraint(0); constraint <
num_constraints(); ++constraint) {
1473 if (constraint_lower_bounds_[constraint] != 0.0 ||
1474 constraint_upper_bounds_[constraint] != 0.0) {
1478 const ColIndex num_slack_variables =
1491 VLOG(1) <<
"Bounds of variable " <<
col.value() <<
" are non-integer (" 1492 << variable_lower_bounds_[
col] <<
", " 1493 << variable_upper_bounds_[
col] <<
").";
1507 bool integer_constraint =
true;
1510 integer_constraint =
false;
1516 if (std::round(
var.coefficient()) !=
var.coefficient()) {
1517 integer_constraint =
false;
1521 if (integer_constraint) {
1528 VLOG(1) <<
"Bounds of constraint " <<
row.value()
1529 <<
" are non-integer (" << constraint_lower_bounds_[
row] <<
", " 1530 << constraint_upper_bounds_[
row] <<
").";
1544 absl::StrAppendFormat(&s,
"\n Var #%d: %s %g",
col.value(),
1548 s +=
"\n------------------------------";
1550 absl::StrAppendFormat(&s,
"\n Constraint #%d: %s %g",
row.value(),
Index ColToIntIndex(ColIndex col)
bool IsVariableBinary(ColIndex col) const
std::string DebugString() const
ColIndex RowToColIndex(RowIndex row)
static constexpr CostScalingAlgorithm NO_COST_SCALING
std::string GetPrettyNonZeroStats() const
Index RowToIntIndex(RowIndex row)
std::string GetObjectiveStatsString() const
const StrictITIVector< ColIndex, VariableType > variable_types() const
const std::vector< ColIndex > & NonBinaryVariablesList() const
void UseTransposeMatrixAsReference()
bool SolutionIsLPFeasible(const DenseRow &solution, Fractional absolute_tolerance) const
const SparseMatrix & GetTransposeSparseMatrix() const
void SetObjectiveCoefficient(ColIndex col, Fractional value)
ColIndex FindOrCreateVariable(const std::string &variable_id)
static constexpr CostScalingAlgorithm CONTAIN_ONE_COST_SCALING
bool IsVariableInteger(ColIndex col) const
RowIndex num_constraints() const
void Swap(LinearProgram *linear_program)
Fractional ApplyObjectiveScalingAndOffset(Fractional value) const
VariableType GetVariableType(ColIndex col) const
void DeleteColumns(const DenseBooleanRow &columns_to_delete)
bool SolutionIsInteger(const DenseRow &solution, Fractional absolute_tolerance) const
std::string GetPrettyProblemStats() const
#define VLOG(verboselevel)
const ColIndex kInvalidCol(-1)
void PopulateFromZero(RowIndex num_rows, ColIndex num_cols)
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
void SetVariableType(ColIndex col, VariableType type)
void SetVariableName(ColIndex col, absl::string_view name)
std::string GetProblemStatusString(ProblemStatus problem_status)
RowIndex EntryRow(EntryIndex i) const
void PopulateFromPermutedMatrix(const Matrix &a, const RowPermutation &row_perm, const ColumnPermutation &inverse_col_perm)
const std::vector< ColIndex > & BinaryVariablesList() const
RowIndex FindOrCreateConstraint(const std::string &constraint_id)
void swap(StrongVector &x)
void SetConstraintBounds(RowIndex row, Fractional lower_bound, Fractional upper_bound)
void PopulateFromSparseMatrix(const SparseMatrix &matrix)
void SetObjectiveOffset(Fractional objective_offset)
bool IsIntegerWithinTolerance(FloatType x, FloatType tolerance)
void Swap(SparseMatrix *matrix)
void PopulateFromSparseVector(const SparseVector &sparse_vector)
void assign(IntType size, const T &v)
SparseMatrix * GetMutableTransposeSparseMatrix()
bool IsFinite(Fractional value)
bool AreBoundsValid(Fractional lower_bound, Fractional upper_bound)
const DenseRow & objective_coefficients() const
Fractional objective_offset() const
const DenseColumn & constraint_upper_bounds() const
VariableStatusRow variable_statuses
bool IsRightMostSquareMatrixIdentity(const SparseMatrix &matrix)
static constexpr CostScalingAlgorithm MEAN_COST_SCALING
void ComputeSlackVariableValues(DenseRow *solution) const
EntryIndex num_entries() const
GlopParameters_CostScalingAlgorithm
Fractional objective_scaling_factor() const
std::string GetDimensionString() const
const DenseColumn & constraint_lower_bounds() const
std::string Stringify(const Fractional x, bool fraction)
typename Iterator::Entry Entry
void SetNumRows(RowIndex num_rows)
bool SolutionIsWithinVariableBounds(const DenseRow &solution, Fractional absolute_tolerance) const
void PopulateFromLinearProgramVariables(const LinearProgram &linear_program)
iterator insert(const_iterator pos, const value_type &x)
#define DCHECK_NE(val1, val2)
std::string GetConstraintStatusString(ConstraintStatus status)
EntryIndex num_entries() const
bool BoundsOfIntegerConstraintsAreInteger(Fractional tolerance) const
Fractional GetObjectiveCoefficientForMinimizationVersion(ColIndex col) const
void PopulateFromPermutedLinearProgram(const LinearProgram &lp, const RowPermutation &row_permutation, const ColumnPermutation &col_permutation)
void AddConstraints(const SparseMatrix &coefficients, const DenseColumn &left_hand_sides, const DenseColumn &right_hand_sides, const StrictITIVector< RowIndex, std::string > &names)
void SetCoefficient(Index index, Fractional value)
ColIndex CreateNewVariable()
bool IsInEquationForm() const
std::string GetProblemStats() const
void PopulateFromTranspose(const Matrix &input)
ColIndex GetFirstSlackVariable() const
void push_back(const value_type &x)
RowIndex CreateNewConstraint()
const SparseColumn & column(ColIndex col) const
ColIndex CreateNewSlackVariable(bool is_integer_slack_variable, Fractional lower_bound, Fractional upper_bound, const std::string &name)
bool SolutionIsMIPFeasible(const DenseRow &solution, Fractional absolute_tolerance) const
SparseColumn * GetMutableSparseColumn(ColIndex col)
RowIndex ColToRowIndex(ColIndex col)
ColIndex num_cols() const
#define DCHECK_GE(val1, val2)
void AddConstraintsWithSlackVariables(const SparseMatrix &coefficients, const DenseColumn &left_hand_sides, const DenseColumn &right_hand_sides, const StrictITIVector< RowIndex, std::string > &names, bool detect_integer_constraints_for_slack)
ColIndex GetSlackVariable(RowIndex row) const
#define CHECK_EQ(val1, val2)
void ApplyPermutation(const Permutation< IndexType > &perm, const ITIVectorType &b, ITIVectorType *result)
const std::string & name() const
const RowIndex kInvalidRow(-1)
ColIndex num_variables() const
Fractional PartialScalarProduct(const DenseRowOrColumn &u, const SparseColumn &v, int max_index)
ConstraintStatusColumn constraint_statuses
void resize(IntType size)
#define DCHECK(condition)
void ComputeMinAndMaxMagnitudes(Fractional *min_magnitude, Fractional *max_magnitude) const
const DenseRow & variable_upper_bounds() const
std::string GetNonZeroStats() const
void DeleteColumns(const DenseBooleanRow &columns_to_delete)
const DenseRow & variable_lower_bounds() const
#define DCHECK_EQ(val1, val2)
void SetVariableBounds(ColIndex col, Fractional lower_bound, Fractional upper_bound)
Fractional RemoveObjectiveScalingAndOffset(Fractional value) const
SparseColumn * mutable_column(ColIndex col)
void DeleteRows(const DenseBooleanColumn &rows_to_delete)
Fractional LookUpValue(RowIndex row, ColIndex col) const
std::string GetVariableStatusString(VariableStatus status)
#define DCHECK_LE(val1, val2)
bool UpdateVariableBoundsToIntersection(const DenseRow &variable_lower_bounds, const DenseRow &variable_upper_bounds)
void SetMaximizationProblem(bool maximize)
Collection of objects used to extend the Constraint Solver library.
std::string GetConstraintName(RowIndex row) const
absl::Span< const double > coefficients
RowIndex num_rows() const
Fractional ScalarProduct(const DenseRowOrColumn1 &u, const DenseRowOrColumn2 &v)
std::string DumpSolution(const DenseRow &variable_values) const
bool AppendRowsFromSparseMatrix(const SparseMatrix &matrix)
void SetObjectiveScalingFactor(Fractional objective_scaling_factor)
std::string GetVariableName(ColIndex col) const
void ClearTransposeMatrix()
Fractional ScaleObjective(GlopParameters::CostScalingAlgorithm method)
std::string GetBoundsStatsString() const
void DeleteRows(RowIndex num_rows, const RowPermutation &permutation)
ColIndex AppendEmptyColumn()
void DeleteSlackVariables()
void SetCoefficient(RowIndex row, ColIndex col, Fractional value)
std::string StringifyMonomial(const Fractional a, const std::string &x, bool fraction)
static constexpr CostScalingAlgorithm MEDIAN_COST_SCALING
StrictITIVector< ColIndex, Fractional > DenseRow
bool BoundsOfIntegerVariablesAreInteger(Fractional tolerance) const
void SetConstraintName(RowIndex row, absl::string_view name)
const std::vector< ColIndex > & IntegerVariablesList() const
#define CHECK_NE(val1, val2)
void PopulateFromInverse(const Permutation &inverse)
void PopulateFromLinearProgram(const LinearProgram &linear_program)
#define DCHECK_LT(val1, val2)
const SparseColumn & GetSparseColumn(ColIndex col) const
EntryIndex num_entries() const
void PopulateFromDual(const LinearProgram &dual, RowToColMapping *duplicated_rows)
void AddSlackVariablesWhereNecessary(bool detect_integer_constraints)