24 #include "ppl-config.h"
38 #if PPL_USE_SPARSE_MATRIX
45 #endif // PPL_USE_SPARSE_MATRIX
47 #ifndef PPL_NOISY_SIMPLEX
48 #define PPL_NOISY_SIMPLEX 0
51 #ifndef PPL_SIMPLEX_USE_MIP_HEURISTIC
52 #define PPL_SIMPLEX_USE_MIP_HEURISTIC 1
71 unsigned long num_iterations = 0;
73 unsigned mip_recursion_level = 0;
76 #endif // PPL_NOISY_SIMPLEX
79 : external_space_dim(dim),
80 internal_space_dim(0),
85 status(PARTIALLY_SATISFIABLE),
86 pricing(PRICING_STEEPEST_EDGE_FLOAT),
89 inherited_constraints(0),
90 first_pending_constraint(0),
93 last_generator(
point()),
97 throw std::length_error(
"PPL::MIP_Problem::MIP_Problem(dim, cs, obj, "
99 "dim exceeds the maximum allowed "
109 : external_space_dim(dim),
110 internal_space_dim(0),
115 status(PARTIALLY_SATISFIABLE),
116 pricing(PRICING_STEEPEST_EDGE_FLOAT),
119 inherited_constraints(0),
120 first_pending_constraint(0),
121 input_obj_function(obj),
123 last_generator(point()),
127 throw std::length_error(
"PPL::MIP_Problem::MIP_Problem(dim, cs, obj, "
129 "dim exceeds the maximum allowed"
134 std::ostringstream s;
135 s <<
"PPL::MIP_Problem::MIP_Problem(dim, cs, obj,"
138 <<
" exceeds dim == "<< dim <<
".";
139 throw std::invalid_argument(s.str());
143 std::ostringstream s;
144 s <<
"PPL::MIP_Problem::MIP_Problem(dim, cs, obj, mode):\n"
146 <<
" exceeds dim == " << dim <<
".";
147 throw std::invalid_argument(s.str());
150 throw std::invalid_argument(
"PPL::MIP_Problem::"
151 "MIP_Problem(d, cs, obj, m):\n"
152 "cs contains strict inequalities.");
156 i = cs.
begin(), i_end = cs.
end(); i != i_end; ++i) {
166 std::ostringstream s;
167 s <<
"PPL::MIP_Problem::add_constraint(c):\n"
169 "this->space_dimension == " << space_dimension() <<
".";
170 throw std::invalid_argument(s.str());
173 throw std::invalid_argument(
"PPL::MIP_Problem::add_constraint(c):\n"
174 "c is a strict inequality.");
176 add_constraint_helper(c);
177 if (status != UNSATISFIABLE) {
178 status = PARTIALLY_SATISFIABLE;
186 std::ostringstream s;
187 s <<
"PPL::MIP_Problem::add_constraints(cs):\n"
189 <<
" exceeds this->space_dimension() == " << this->space_dimension()
191 throw std::invalid_argument(s.str());
194 throw std::invalid_argument(
"PPL::MIP_Problem::add_constraints(cs):\n"
195 "cs contains strict inequalities.");
198 i = cs.
begin(), i_end = cs.
end(); i != i_end; ++i) {
199 add_constraint_helper(*i);
201 if (status != UNSATISFIABLE) {
202 status = PARTIALLY_SATISFIABLE;
210 std::ostringstream s;
211 s <<
"PPL::MIP_Problem::set_objective_function(obj):\n"
213 <<
" exceeds this->space_dimension == " << space_dimension()
215 throw std::invalid_argument(s.str());
217 input_obj_function = obj;
218 if (status == UNBOUNDED || status == OPTIMIZED) {
219 status = SATISFIABLE;
226 if (is_satisfiable()) {
227 return last_generator;
230 throw std::domain_error(
"PPL::MIP_Problem::feasible_point():\n"
231 "*this is not satisfiable.");
238 return last_generator;
241 throw std::domain_error(
"PPL::MIP_Problem::optimizing_point():\n"
242 "*this does not have an optimizing point.");
260 case PARTIALLY_SATISFIABLE:
273 #if PPL_NOISY_SIMPLEX
274 mip_recursion_level = 0;
275 #endif // PPL_NOISY_SIMPLEX
276 if (is_mip_satisfiable(relaxed.
lp, relaxed.
i_vars, p)) {
284 return (x.
status == SATISFIABLE);
306 case PARTIALLY_SATISFIABLE:
313 if (x.
status == UNBOUNDED) {
317 PPL_ASSERT(x.
status == OPTIMIZED);
339 bool have_incumbent_solution =
false;
343 return_value = solve_mip(have_incumbent_solution,
344 incumbent_solution, g,
348 switch (return_value) {
378 throw std::length_error(
"PPL::MIP_Problem::"
379 "add_space_dimensions_and_embed(m):\n"
380 "adding m new space dimensions exceeds "
381 "the maximum allowed space dimension.");
383 external_space_dim += m;
384 if (status != UNSATISFIABLE) {
385 status = PARTIALLY_SATISFIABLE;
394 throw std::invalid_argument(
"PPL::MIP_Problem::"
395 "add_to_integer_space_dimension(i_vars):\n"
396 "*this and i_vars are dimension"
400 i_variables.insert(i_vars.begin(), i_vars.end());
403 if (i_variables.size() != original_size && status != UNSATISFIABLE) {
404 status = PARTIALLY_SATISFIABLE;
411 for (row_index = base.size(); row_index-- > 0; ) {
412 if (base[row_index] == var_index) {
424 const dimension_type removing_column = mapping[1+var_index].second;
430 if (is_in_base(removing_column, base_index)) {
432 unfeasible_tableau_row = base_index;
434 base[base_index] = 0;
437 PPL_ASSERT(!is_in_base(mapping[1+var_index].first, base_index));
441 tableau.remove_column(removing_column);
444 mapping[1+var_index].second = 0;
449 if (base[i] > removing_column) {
455 if (mapping[i].first > removing_column) {
458 if (mapping[i].second > removing_column) {
463 return unfeasible_tableau_row;
492 std::deque<bool>& is_tableau_constraint,
493 std::deque<bool>& is_satisfied_inequality,
494 std::deque<bool>& is_nonnegative_variable,
495 std::deque<bool>& is_remergeable_variable)
const {
497 PPL_ASSERT(is_tableau_constraint.empty()
498 && is_satisfied_inequality.empty()
499 && is_nonnegative_variable.empty()
500 && is_remergeable_variable.empty());
505 = cs_num_rows - first_pending_constraint;
509 additional_tableau_rows = cs_num_pending;
510 additional_slack_variables = 0;
517 is_tableau_constraint.insert(is_tableau_constraint.end(),
518 cs_num_pending,
true);
523 is_satisfied_inequality.insert(is_satisfied_inequality.end(),
524 cs_num_pending,
false);
528 is_nonnegative_variable.insert(is_nonnegative_variable.end(),
529 cs_space_dim,
false);
533 is_remergeable_variable.insert(is_remergeable_variable.end(),
534 internal_space_dim,
false);
539 if (mapping_size > 0) {
543 if (mapping[i + 1].second == 0) {
544 is_nonnegative_variable[i] =
true;
554 for (
dimension_type i = cs_num_rows; i-- > first_pending_constraint; ) {
560 const bool found_a_nonzero_coeff = (nonzero_coeff_column_index != cs_i_end);
561 const bool found_many_nonzero_coeffs
562 = (found_a_nonzero_coeff
568 if (found_many_nonzero_coeffs) {
570 ++additional_slack_variables;
577 if (cs_i.
is_inequality() && is_satisfied(cs_i, last_generator)) {
578 is_satisfied_inequality[i - first_pending_constraint] =
true;
583 if (!found_a_nonzero_coeff) {
600 is_tableau_constraint[i - first_pending_constraint] =
false;
601 --additional_tableau_rows;
637 const dimension_type nonzero_var_index = nonzero_coeff_column_index - 1;
643 if (sgn_a == sgn_b) {
645 ++additional_slack_variables;
650 is_nonnegative_variable[nonzero_var_index] =
true;
653 else if (sgn_b < 0) {
654 is_nonnegative_variable[nonzero_var_index] =
true;
655 ++additional_slack_variables;
658 else if (sgn_a > 0) {
659 if (!is_nonnegative_variable[nonzero_var_index]) {
660 is_nonnegative_variable[nonzero_var_index] =
true;
661 if (nonzero_coeff_column_index < mapping_size) {
663 PPL_ASSERT(nonzero_var_index < internal_space_dim);
664 is_remergeable_variable[nonzero_var_index] =
true;
667 is_tableau_constraint[i - first_pending_constraint] =
false;
668 --additional_tableau_rows;
673 ++additional_slack_variables;
686 std::deque<bool> is_tableau_constraint;
687 std::deque<bool> is_satisfied_inequality;
688 std::deque<bool> is_nonnegative_variable;
689 std::deque<bool> is_remergeable_variable;
690 if (!parse_constraints(additional_tableau_rows,
691 additional_slack_vars,
692 is_tableau_constraint,
693 is_satisfied_inequality,
694 is_nonnegative_variable,
695 is_remergeable_variable)) {
696 status = UNSATISFIABLE;
702 std::vector<dimension_type> unfeasible_tableau_rows;
704 if (!is_remergeable_variable[i]) {
711 unfeasible_tableau_rows.push_back(unfeasible_row);
716 const dimension_type old_tableau_num_cols = tableau.num_columns();
717 const dimension_type first_free_tableau_index = old_tableau_num_cols - 1;
721 if (external_space_dim > internal_space_dim) {
722 const dimension_type space_diff = external_space_dim - internal_space_dim;
728 if (is_nonnegative_variable[internal_space_dim + i]) {
730 mapping.push_back(std::make_pair(positive, 0));
732 ++additional_problem_vars;
736 mapping.push_back(std::make_pair(positive, positive + 1));
738 additional_problem_vars += 2;
744 if (additional_tableau_rows > 0) {
745 tableau.add_zero_rows(additional_tableau_rows);
761 =
static_cast<dimension_type>(std::count(is_satisfied_inequality.begin(),
762 is_satisfied_inequality.end(),
765 = unfeasible_tableau_rows.size();
767 PPL_ASSERT(additional_tableau_rows >= num_satisfied_inequalities);
769 = (additional_tableau_rows - num_satisfied_inequalities)
770 + unfeasible_tableau_rows_size;
773 = additional_problem_vars
774 + additional_slack_vars
775 + additional_artificial_vars;
777 if (additional_tableau_columns > 0) {
778 tableau.add_zero_columns(additional_tableau_columns);
787 std::deque<bool> worked_out_row(tableau_num_rows,
false);
791 base.insert(base.end(), additional_tableau_rows, 0);
797 = tableau_num_cols - additional_artificial_vars - 1;
804 = (additional_artificial_vars > 0)
810 i = input_cs.size() - first_pending_constraint; i-- > 0; ) {
811 if (!is_tableau_constraint[i]) {
815 Row& tableau_k = tableau[--k];
818 const Constraint&
c = *(input_cs[i + first_pending_constraint]);
821 j_end = c_e.
end(); j != j_end; ++j) {
822 Coefficient_traits::const_reference coeff_sd = *j;
823 const std::pair<dimension_type, dimension_type> mapped
824 = mapping[j.variable().space_dimension()];
825 itr = tableau_k.
insert(itr, mapped.first, coeff_sd);
827 if (mapped.second != 0) {
828 itr = tableau_k.
insert(itr, mapped.second);
834 tableau_k.
insert(itr, mapping[0].first, inhomo);
836 if (mapping[0].second != 0) {
837 itr = tableau_k.
insert(itr, mapping[0].second);
848 if (is_satisfied_inequality[i]) {
849 base[k] = slack_index;
850 worked_out_row[k] =
true;
854 if (k != j && base[j] != 0 && tableau_k.
get(base[j]) != 0) {
864 Row& tableau_i = tableau[i];
865 if (tableau_i.
get(0) > 0) {
867 j = tableau_i.
begin(), j_end = tableau_i.
end();
886 for (
dimension_type i = 0; i < unfeasible_tableau_rows_size; ++i) {
887 tableau[unfeasible_tableau_rows[i]].insert(artificial_index,
889 cost_itr = working_cost.insert(cost_itr, artificial_index);
891 base[unfeasible_tableau_rows[i]] = artificial_index;
897 for (
dimension_type i = old_tableau_num_rows; i < tableau_num_rows; ++i) {
898 if (worked_out_row[i]) {
902 cost_itr = working_cost.insert(cost_itr, artificial_index);
904 base[i] = artificial_index;
919 itr = working_cost.lower_bound(itr, base[i]);
920 if (itr != working_cost.end() && itr.
index() == base[i] && *itr != 0) {
923 itr = working_cost.end();
929 if (space_dimension() == 0) {
931 last_generator = point();
939 if (tableau_num_rows == 0) {
940 if (is_unbounded_obj_function(input_obj_function, mapping, opt_mode)) {
942 last_generator = point();
943 last_generator.set_space_dimension(space_dimension());
953 last_generator = point();
954 last_generator.set_space_dimension(space_dimension());
959 const bool first_phase_successful
960 = (get_control_parameter(PRICING) == PRICING_STEEPEST_EDGE_FLOAT)
961 ? compute_simplex_using_steepest_edge_float()
962 : compute_simplex_using_exact_pricing();
964 #if PPL_NOISY_SIMPLEX
965 std::cout <<
"MIP_Problem::process_pending_constraints(): "
966 <<
"1st phase ended at iteration " << num_iterations
968 #endif // PPL_NOISY_SIMPLEX
970 if (!first_phase_successful || working_cost.get(0) != 0) {
972 status = UNSATISFIABLE;
977 if (begin_artificials != 0) {
978 erase_artificials(begin_artificials, end_artificials);
981 status = SATISFIABLE;
995 assign(
double& d,
const mpz_class&
c) {
999 template <
typename T,
typename Policy>
1011 const dimension_type tableau_num_columns = tableau.num_columns();
1012 PPL_ASSERT(tableau_num_rows == base.size());
1013 double current_value = 0.0;
1016 double float_tableau_value;
1017 double float_tableau_denom;
1019 const int cost_sign =
sgn(working_cost.get(working_cost.size() - 1));
1025 #if PPL_USE_SPARSE_MATRIX
1027 const dimension_type tableau_num_columns_minus_1 = tableau_num_columns - 1;
1031 static std::vector<std::pair<dimension_type, double> > columns;
1034 columns.reserve(working_cost.size() - 2);
1039 = working_cost.find(tableau_num_columns_minus_1);
1040 for ( ; i != i_end; ++i) {
1041 if (
sgn(*i) == cost_sign) {
1042 columns.push_back(std::make_pair(i.
index(), 1.0));
1047 const Row& tableau_i = tableau[i];
1048 assign(float_tableau_denom, tableau_i.
get(base[i]));
1051 std::vector<std::pair<dimension_type, double> >::iterator k
1053 std::vector<std::pair<dimension_type, double> >::iterator k_end
1055 while (j != j_end && k != k_end) {
1057 while (k != k_end && column > k->first) {
1063 if (k->first > column) {
1067 PPL_ASSERT(k->first == column);
1068 PPL_ASSERT(tableau_i.
get(base[i]) != 0);
1070 assign(float_tableau_value, *j);
1071 float_tableau_value /= float_tableau_denom;
1072 float_tableau_value *= float_tableau_value;
1073 k->second += float_tableau_value;
1082 for (std::vector<std::pair<dimension_type, double> >::const_reverse_iterator
1083 i = columns.rbegin(), i_end = columns.rend(); i != i_end; ++i) {
1084 const double challenger_value = sqrt(i->second);
1085 if (entering_index == 0 || challenger_value > current_value) {
1086 current_value = challenger_value;
1087 entering_index = i->first;
1091 #else // !PPL_USE_SPARSE_MATRIX
1093 double challenger_numer = 0.0;
1094 double challenger_denom = 0.0;
1096 Coefficient_traits::const_reference cost_j = working_cost.get(j);
1097 if (
sgn(cost_j) == cost_sign) {
1101 assign(challenger_numer, cost_j);
1102 challenger_numer = std::abs(challenger_numer);
1105 challenger_denom = 1.0;
1107 const Row& tableau_i = tableau[i];
1108 Coefficient_traits::const_reference tableau_ij = tableau_i[j];
1109 if (tableau_ij != 0) {
1110 PPL_ASSERT(tableau_i[base[i]] != 0);
1111 assign(float_tableau_value, tableau_ij);
1112 assign(float_tableau_denom, tableau_i[base[i]]);
1113 float_tableau_value /= float_tableau_denom;
1114 challenger_denom += float_tableau_value * float_tableau_value;
1117 double challenger_value = sqrt(challenger_denom);
1120 if (entering_index == 0 || challenger_value > current_value) {
1121 current_value = challenger_value;
1128 #endif // !PPL_USE_SPARSE_MATRIX
1130 return entering_index;
1137 PPL_ASSERT(tableau_num_rows == base.size());
1141 std::vector<Coefficient> norm_factor(tableau_num_rows);
1148 lcm_assign(lcm_basis, lcm_basis, tableau[i].
get(base[i]));
1156 lcm_basis *= lcm_basis;
1157 swap(squared_lcm_basis, lcm_basis);
1169 const int cost_sign =
sgn(working_cost.get(working_cost.size() - 1));
1175 #if PPL_USE_SPARSE_MATRIX
1177 const dimension_type tableau_num_columns = tableau.num_columns();
1178 const dimension_type tableau_num_columns_minus_1 = tableau_num_columns - 1;
1182 static std::vector<std::pair<dimension_type, Coefficient> > columns;
1187 columns.reserve(tableau_num_columns - 2);
1192 = working_cost.find(tableau_num_columns_minus_1);
1193 for ( ; i != i_end; ++i) {
1194 if (
sgn(*i) == cost_sign) {
1195 columns.push_back(std::pair<dimension_type, Coefficient>
1196 (i.
index(), squared_lcm_basis));
1201 const Row& tableau_i = tableau[i];
1204 std::vector<std::pair<dimension_type, Coefficient> >::iterator
1205 k = columns.begin();
1206 std::vector<std::pair<dimension_type, Coefficient> >::iterator
1207 k_end = columns.end();
1208 while (j != j_end) {
1209 while (k != k_end && j.
index() > k->first) {
1215 PPL_ASSERT(j.
index() <= k->first);
1216 if (j.
index() < k->first) {
1220 Coefficient_traits::const_reference tableau_ij = *j;
1222 #if PPL_USE_SPARSE_MATRIX
1223 scalar_value = tableau_ij * norm_factor[i];
1230 if (tableau_ij != 0) {
1231 scalar_value = tableau_ij * norm_factor[i];
1242 for (std::vector<std::pair<dimension_type, Coefficient> >::reverse_iterator
1243 k = columns.rbegin(), k_end = columns.rend(); k != k_end; ++k) {
1244 itr = working_cost.lower_bound(itr, k->first);
1245 if (itr != working_cost.end() && itr.
index() == k->first) {
1248 challenger_numer = (*itr) * (*itr);
1250 if (entering_index == 0) {
1251 swap(current_numer, challenger_numer);
1252 swap(current_denom, k->second);
1253 entering_index = k->first;
1256 challenger_value = challenger_numer * current_denom;
1257 current_value = current_numer * k->second;
1259 if (challenger_value > current_value) {
1260 swap(current_numer, challenger_numer);
1261 swap(current_denom, k->second);
1262 entering_index = k->first;
1266 PPL_ASSERT(working_cost.get(k->first) == 0);
1268 if (entering_index == 0) {
1270 swap(current_denom, k->second);
1271 entering_index = k->first;
1275 if (0 >
sgn(current_numer) *
sgn(k->second)) {
1277 swap(current_denom, k->second);
1278 entering_index = k->first;
1283 #else // !PPL_USE_SPARSE_MATRIX
1287 Coefficient_traits::const_reference cost_j = working_cost[j];
1288 if (
sgn(cost_j) == cost_sign) {
1292 challenger_numer = cost_j * cost_j;
1295 challenger_denom = squared_lcm_basis;
1297 Coefficient_traits::const_reference tableau_ij = tableau[i][j];
1301 if (tableau_ij != 0) {
1302 scalar_value = tableau_ij * norm_factor[i];
1307 if (entering_index == 0) {
1308 swap(current_numer, challenger_numer);
1309 swap(current_denom, challenger_denom);
1313 challenger_value = challenger_numer * current_denom;
1314 current_value = current_numer * challenger_denom;
1316 if (challenger_value > current_value) {
1317 swap(current_numer, challenger_numer);
1318 swap(current_denom, challenger_denom);
1325 #endif // !PPL_USE_SPARSE_MATRIX
1327 return entering_index;
1341 const int cost_sign =
sgn(working_cost.get(cost_sign_index));
1342 PPL_ASSERT(cost_sign != 0);
1348 = working_cost.find(cost_sign_index);
1349 for ( ; i != i_end; ++i) {
1350 if (
sgn(*i) == cost_sign) {
1365 Coefficient_traits::const_reference x_k = x.
get(k);
1366 Coefficient_traits::const_reference y_k = y.
get(k);
1367 PPL_ASSERT(y_k != 0 && x_k != 0);
1373 normalize2(x_k, y_k, normalized_x_k, normalized_y_k);
1378 PPL_ASSERT(x.
get(k) == 0);
1380 #if PPL_USE_SPARSE_MATRIX
1381 PPL_ASSERT(x.
find(k) == x.
end());
1389 #if PPL_USE_SPARSE_MATRIX
1398 Coefficient_traits::const_reference x_k = x.
get(k);
1399 Coefficient_traits::const_reference y_k = y.
get(k);
1400 PPL_ASSERT(y_k != 0 && x_k != 0);
1406 normalize2(x_k, y_k, normalized_x_k, normalized_y_k);
1411 PPL_ASSERT(x[k] == 0);
1417 #endif // defined(PPL_USE_SPARSE_MATRIX)
1422 const std::vector<std::pair<dimension_type, dimension_type> >& mapping,
1426 i_end = x.
end(); i != i_end; ++i) {
1431 if (mapping[i.variable().space_dimension()].second != 0) {
1453 const Row& tableau_out = tableau[exiting_base_index];
1456 Row& tableau_i = tableau[i];
1457 if (i != exiting_base_index && tableau_i.
get(entering_var_index) != 0) {
1462 if (working_cost.get(entering_var_index) != 0) {
1466 base[exiting_base_index] = entering_var_index;
1483 const Row& t_i = tableau[i];
1484 const int num_sign =
sgn(t_i.
get(entering_var_index));
1485 if (num_sign != 0 && num_sign ==
sgn(t_i.
get(base[i]))) {
1486 exiting_base_index = i;
1491 if (exiting_base_index == tableau_num_rows) {
1492 return tableau_num_rows;
1499 Coefficient t_e0 = tableau[exiting_base_index].get(0);
1500 Coefficient t_ee = tableau[exiting_base_index].get(entering_var_index);
1501 for (
dimension_type i = exiting_base_index + 1; i < tableau_num_rows; ++i) {
1502 const Row& t_i = tableau[i];
1503 Coefficient_traits::const_reference t_ie = t_i.
get(entering_var_index);
1504 const int t_ie_sign =
sgn(t_ie);
1505 if (t_ie_sign != 0 && t_ie_sign ==
sgn(t_i.
get(base[i]))) {
1507 Coefficient_traits::const_reference t_i0 = t_i.
get(0);
1510 current_min *= t_e0;
1515 current_min -= challenger;
1516 const int sign =
sgn(current_min);
1518 || (sign == 0 && base[i] < base[exiting_base_index])) {
1519 exiting_base_index = i;
1526 return exiting_base_index;
1533 const unsigned long allowed_non_increasing_loops = 200;
1534 unsigned long non_increased_times = 0;
1535 bool textbook_pricing =
false;
1543 cost_sgn_coeff = working_cost.get(working_cost.size() - 1);
1544 current_numer = working_cost.get(0);
1545 if (cost_sgn_coeff < 0) {
1549 PPL_ASSERT(tableau.num_columns() == working_cost.size());
1556 ? textbook_entering_index()
1557 : steepest_edge_float_entering_index();
1560 if (entering_var_index == 0) {
1566 = get_exiting_base_index(entering_var_index);
1568 if (exiting_base_index == tableau_num_rows) {
1580 pivot(entering_var_index, exiting_base_index);
1585 cost_sgn_coeff = working_cost.get(working_cost.size() - 1);
1587 challenger = working_cost.get(0);
1588 if (cost_sgn_coeff < 0) {
1591 challenger *= current_denom;
1593 current *= current_numer;
1594 #if PPL_NOISY_SIMPLEX
1596 if (num_iterations % 200 == 0) {
1597 std::cout <<
"Primal simplex: iteration " << num_iterations
1598 <<
"." << std::endl;
1600 #endif // PPL_NOISY_SIMPLEX
1602 PPL_ASSERT(challenger >= current);
1605 if (challenger == current) {
1606 ++non_increased_times;
1609 if (non_increased_times > allowed_non_increasing_loops) {
1610 textbook_pricing =
true;
1616 non_increased_times = 0;
1617 textbook_pricing =
false;
1619 current_numer = working_cost.get(0);
1620 if (cost_sgn_coeff < 0) {
1630 PPL_ASSERT(tableau.num_columns() == working_cost.size());
1631 PPL_ASSERT(get_control_parameter(PRICING) == PRICING_STEEPEST_EDGE_EXACT
1632 || get_control_parameter(PRICING) == PRICING_TEXTBOOK);
1635 const bool textbook_pricing
1636 = (PRICING_TEXTBOOK == get_control_parameter(PRICING));
1642 ? textbook_entering_index()
1643 : steepest_edge_exact_entering_index();
1645 if (entering_var_index == 0) {
1651 = get_exiting_base_index(entering_var_index);
1653 if (exiting_base_index == tableau_num_rows) {
1665 pivot(entering_var_index, exiting_base_index);
1666 #if PPL_NOISY_SIMPLEX
1668 if (num_iterations % 200 == 0) {
1669 std::cout <<
"Primal simplex: iteration " << num_iterations
1670 <<
"." << std::endl;
1672 #endif // PPL_NOISY_SIMPLEX
1681 PPL_ASSERT(0 < begin_artificials && begin_artificials < end_artificials);
1683 const dimension_type old_last_column = tableau.num_columns() - 1;
1687 if (begin_artificials <= base[i] && base[i] < end_artificials) {
1689 Row& tableau_i = tableau[i];
1690 bool redundant =
true;
1694 if (j != j_end && j.
index() == 0) {
1697 for ( ; (j != j_end) && (j.
index() < begin_artificials); ++j) {
1699 pivot(j.
index(), i);
1708 if (i < tableau_n_rows) {
1711 tableau_i.
m_swap(tableau[tableau_n_rows]);
1712 base[i] = base[tableau_n_rows];
1715 tableau.remove_trailing_rows(1);
1723 const dimension_type num_artificials = end_artificials - begin_artificials;
1724 tableau.remove_trailing_columns(num_artificials);
1727 const dimension_type new_last_column = tableau.num_columns() - 1;
1729 tableau[i].reset(new_last_column);
1742 Coefficient_traits::const_reference old_cost
1743 = working_cost.get(old_last_column);
1744 if (old_cost == 0) {
1745 working_cost.reset(new_last_column);
1748 working_cost.insert(new_last_column, old_cost);
1754 = working_cost.size() - num_artificials;
1755 working_cost.shrink(working_cost_new_size);
1762 if (external_space_dim == 0) {
1770 std::vector<Coefficient> numer(external_space_dim);
1771 std::vector<Coefficient> denom(external_space_dim);
1786 if (is_in_base(original_var, row)) {
1787 const Row& t_row = tableau[row];
1788 Coefficient_traits::const_reference t_row_original_var
1789 = t_row.
get(original_var);
1790 if (t_row_original_var > 0) {
1792 denom_i = t_row_original_var;
1795 numer_i = t_row.
get(0);
1805 if (split_var != 0) {
1809 if (is_in_base(split_var, row)) {
1810 const Row& t_row = tableau[row];
1811 Coefficient_traits::const_reference t_row_split_var
1812 = t_row.
get(split_var);
1813 if (t_row_split_var > 0) {
1815 split_denom = t_row_split_var;
1818 split_numer = t_row.
get(0);
1841 PPL_ASSERT(external_space_dim > 0);
1850 numer[i] *= denom[i];
1866 PPL_ASSERT(status == SATISFIABLE
1867 || status == UNBOUNDED
1868 || status == OPTIMIZED);
1870 if (status == UNBOUNDED || status == OPTIMIZED) {
1875 input_obj_function.get_row(new_cost);
1880 i_end = new_cost.
end(); i != i_end; ++i) {
1890 swap(tmp_cost, working_cost);
1899 i_end = new_cost.
end(); i != i_end; ++i) {
1903 itr = working_cost.insert(itr, original_var, *i);
1904 if (mapping[index].second != 0) {
1905 itr = working_cost.insert(itr, split_var);
1917 itr = working_cost.lower_bound(itr, base_i);
1918 if (itr != working_cost.end() && itr.
index() == base_i && *itr != 0) {
1920 itr = working_cost.end();
1926 const bool second_phase_successful
1927 = (get_control_parameter(PRICING) == PRICING_STEEPEST_EDGE_FLOAT)
1928 ? compute_simplex_using_steepest_edge_float()
1929 : compute_simplex_using_exact_pricing();
1930 compute_generator();
1931 #if PPL_NOISY_SIMPLEX
1932 std::cout <<
"MIP_Problem::second_phase(): 2nd phase ended at iteration "
1934 <<
"." << std::endl;
1935 #endif // PPL_NOISY_SIMPLEX
1936 status = second_phase_successful ? OPTIMIZED : UNBOUNDED;
1946 if (space_dimension() < ep_space_dim) {
1947 throw std::invalid_argument(
"PPL::MIP_Problem::"
1948 "evaluate_objective_function(p, n, d):\n"
1949 "*this and p are dimension incompatible.");
1951 if (!evaluating_point.
is_point()) {
1952 throw std::invalid_argument(
"PPL::MIP_Problem::"
1953 "evaluate_objective_function(p, n, d):\n"
1954 "p is not a point.");
1959 = std::min(ep_space_dim, input_obj_function.space_dimension());
1960 input_obj_function.scalar_product_assign(numer,
1961 evaluating_point.
expr,
1962 0, working_space_dim + 1);
1970 #if PPL_NOISY_SIMPLEX
1972 #endif // PPL_NOISY_SIMPLEX
1983 case PARTIALLY_SATISFIABLE:
1988 if (tableau.num_columns() == 0) {
1991 x.
tableau.add_zero_columns(2);
1993 x.
mapping.push_back(std::make_pair(0, 0));
2006 return status != UNSATISFIABLE;
2016 mpq_class& incumbent_solution_value,
2047 if (have_incumbent_solution
2049 && tmp_rational <= incumbent_solution_value)
2051 && tmp_rational >= incumbent_solution_value))) {
2057 bool found_satisfiable_generator =
true;
2059 Coefficient_traits::const_reference p_divisor = p.
divisor();
2064 for (Variables_Set::const_iterator v_begin = i_vars.begin(),
2065 v_end = i_vars.end(); v_begin != v_end; ++v_begin) {
2067 if (gcd != p_divisor) {
2068 non_int_dim = *v_begin;
2069 found_satisfiable_generator =
false;
2073 if (found_satisfiable_generator) {
2079 incumbent_solution_point = p;
2082 if (!have_incumbent_solution
2084 && tmp_rational > incumbent_solution_value)
2085 || tmp_rational < incumbent_solution_value) {
2086 incumbent_solution_value = tmp_rational;
2087 incumbent_solution_point = p;
2088 have_incumbent_solution =
true;
2089 #if PPL_NOISY_SIMPLEX
2093 std::cout <<
"MIP_Problem::solve_mip(): "
2094 <<
"new value found: " << numer <<
"/" << denom
2095 <<
"." << std::endl;
2096 #endif // PPL_NOISY_SIMPLEX
2106 tmp_rational.canonicalize();
2112 #if PPL_NOISY_SIMPLEX
2113 using namespace IO_Operators;
2114 std::cout <<
"MIP_Problem::solve_mip(): "
2115 <<
"descending with: "
2116 << (
Variable(non_int_dim) <= tmp_coeff1)
2117 <<
"." << std::endl;
2118 #endif // PPL_NOISY_SIMPLEX
2119 solve_mip(have_incumbent_solution, incumbent_solution_value,
2120 incumbent_solution_point, mip_aux, i_vars);
2124 #if PPL_NOISY_SIMPLEX
2125 using namespace IO_Operators;
2126 std::cout <<
"MIP_Problem::solve_mip(): "
2127 <<
"descending with: "
2128 << (
Variable(non_int_dim) >= tmp_coeff2)
2129 <<
"." << std::endl;
2130 #endif // PPL_NOISY_SIMPLEX
2131 solve_mip(have_incumbent_solution, incumbent_solution_value,
2132 incumbent_solution_point, mip, i_vars);
2142 const std::vector<Constraint*>& input_cs = mip.
input_cs;
2144 Coefficient_traits::const_reference last_generator_divisor
2152 for (Variables_Set::const_iterator v_it = i_vars.begin(),
2153 v_end = i_vars.end(); v_it != v_end; ++v_it) {
2156 last_generator_divisor);
2157 if (gcd != last_generator_divisor) {
2158 candidate_variables.
insert(*v_it);
2162 if (candidate_variables.empty()) {
2168 std::deque<bool> satisfiable_constraints(input_cs_num_rows,
false);
2172 if (input_cs[i]->is_equality()
2173 || is_saturated(*(input_cs[i]), last_generator)) {
2174 satisfiable_constraints[i] =
true;
2180 std::vector<dimension_type>
2186 if (!satisfiable_constraints[i]) {
2192 for (Variables_Set::const_iterator v_it = candidate_variables.begin(),
2193 v_end = candidate_variables.end(); v_it != v_end; ++v_it) {
2194 if (*v_it >= input_cs[i]->space_dimension()) {
2197 if (input_cs[i]->coefficient(
Variable(*v_it)) != 0) {
2198 ++num_appearances[*v_it];
2202 for (Variables_Set::const_iterator v_it = candidate_variables.begin(),
2203 v_end = candidate_variables.end(); v_it != v_end; ++v_it) {
2205 if (n >= winning_num_appearances) {
2206 winning_num_appearances = n;
2207 branching_index = *v_it;
2217 #if PPL_NOISY_SIMPLEX
2218 ++mip_recursion_level;
2219 std::cout <<
"MIP_Problem::is_mip_satisfiable(): "
2220 <<
"entering recursion level " << mip_recursion_level
2221 <<
"." << std::endl;
2222 #endif // PPL_NOISY_SIMPLEX
2227 #if PPL_NOISY_SIMPLEX
2228 std::cout <<
"MIP_Problem::is_mip_satisfiable(): "
2229 <<
"exiting from recursion level " << mip_recursion_level
2230 <<
"." << std::endl;
2231 --mip_recursion_level;
2232 #endif // PPL_NOISY_SIMPLEX
2239 bool found_satisfiable_generator =
true;
2242 Coefficient_traits::const_reference p_divisor = p.
divisor();
2244 #if PPL_SIMPLEX_USE_MIP_HEURISTIC
2245 found_satisfiable_generator
2246 = choose_branching_variable(mip, i_vars, non_int_dim);
2252 for (Variables_Set::const_iterator v_begin = i_vars.begin(),
2253 v_end = i_vars.end(); v_begin != v_end; ++v_begin) {
2255 if (gcd != p_divisor) {
2256 non_int_dim = *v_begin;
2257 found_satisfiable_generator =
false;
2263 if (found_satisfiable_generator) {
2272 tmp_rational.canonicalize();
2278 #if PPL_NOISY_SIMPLEX
2279 using namespace IO_Operators;
2280 std::cout <<
"MIP_Problem::is_mip_satisfiable(): "
2281 <<
"descending with: "
2282 << (
Variable(non_int_dim) <= tmp_coeff1)
2283 <<
"." << std::endl;
2284 #endif // PPL_NOISY_SIMPLEX
2285 if (is_mip_satisfiable(mip_aux, i_vars, p)) {
2286 #if PPL_NOISY_SIMPLEX
2287 std::cout <<
"MIP_Problem::is_mip_satisfiable(): "
2288 <<
"exiting from recursion level " << mip_recursion_level
2289 <<
"." << std::endl;
2290 --mip_recursion_level;
2291 #endif // PPL_NOISY_SIMPLEX
2296 #if PPL_NOISY_SIMPLEX
2297 using namespace IO_Operators;
2298 std::cout <<
"MIP_Problem::is_mip_satisfiable(): "
2299 <<
"descending with: "
2300 << (
Variable(non_int_dim) >= tmp_coeff2)
2301 <<
"." << std::endl;
2302 #endif // PPL_NOISY_SIMPLEX
2303 const bool satisfiable = is_mip_satisfiable(mip, i_vars, p);
2304 #if PPL_NOISY_SIMPLEX
2305 std::cout <<
"MIP_Problem::is_mip_satisfiable(): "
2306 <<
"exiting from recursion level " << mip_recursion_level
2307 <<
"." << std::endl;
2308 --mip_recursion_level;
2309 #endif // PPL_NOISY_SIMPLEX
2323 if (inherited_constraints > input_cs_num_rows) {
2325 cerr <<
"The MIP_Problem claims to have inherited from its ancestors "
2326 <<
"more constraints than are recorded in this->input_cs."
2333 if (first_pending_constraint > input_cs_num_rows) {
2335 cerr <<
"The MIP_Problem claims to have pending constraints "
2336 <<
"that are not recorded in this->input_cs."
2343 if (!tableau.OK() || !last_generator.OK()) {
2349 if (input_cs[i]->is_strict_inequality()) {
2351 cerr <<
"The feasible region of the MIP_Problem is defined by "
2352 <<
"a constraint system containing strict inequalities."
2361 if (external_space_dim < internal_space_dim) {
2363 cerr <<
"The MIP_Problem claims to have an internal space dimension "
2364 <<
"greater than its external space dimension."
2371 if (external_space_dim > internal_space_dim
2372 && status != UNSATISFIABLE
2373 && status != PARTIALLY_SATISFIABLE) {
2375 cerr <<
"The MIP_Problem claims to have a pending space dimension "
2376 <<
"addition, but the status is incompatible."
2384 if (external_space_dim < input_obj_function.space_dimension()) {
2386 cerr <<
"The MIP_Problem and the objective function have "
2387 <<
"incompatible space dimensions ("
2388 << external_space_dim <<
" < "
2389 << input_obj_function.space_dimension() <<
")."
2396 if (status != UNSATISFIABLE && initialized) {
2399 if (internal_space_dim != last_generator.space_dimension()) {
2401 cerr <<
"The MIP_Problem and the cached feasible point have "
2402 <<
"incompatible space dimensions ("
2403 << internal_space_dim <<
" != "
2404 << last_generator.space_dimension() <<
")."
2412 if (!is_satisfied(*(input_cs[i]), last_generator)) {
2414 cerr <<
"The cached feasible point does not belong to "
2415 <<
"the feasible region of the MIP_Problem."
2425 if (!i_variables.empty()) {
2431 for (Variables_Set::const_iterator v_it = i_variables.begin(),
2432 v_end = i_variables.end(); v_it != v_end; ++v_it) {
2434 last_generator.divisor());
2435 if (gcd != last_generator.divisor()) {
2442 const dimension_type tableau_num_columns = tableau.num_columns();
2445 if (tableau_num_rows != base.size()) {
2447 cerr <<
"tableau and base have incompatible sizes" << endl;
2454 if (mapping.size() != internal_space_dim + 1) {
2456 cerr <<
"The internal space dimension and `mapping' "
2457 <<
"have incompatible sizes" << endl;
2464 if (tableau_num_columns != working_cost.size()) {
2466 cerr <<
"tableau and working_cost have incompatible sizes" << endl;
2474 if (base[i] > tableau_num_columns) {
2476 cerr <<
"base contains an invalid column index" << endl;
2485 typedef std::vector<std::pair<dimension_type, dimension_type> >
2487 pair_vector_t vars_in_base;
2489 vars_in_base.push_back(std::make_pair(base[i], i));
2492 std::sort(vars_in_base.begin(), vars_in_base.end());
2495 const Row& tableau_j = tableau[j];
2496 pair_vector_t::iterator i = vars_in_base.
begin();
2497 pair_vector_t::iterator i_end = vars_in_base.end();
2500 for ( ; i != i_end && itr != itr_end; ++i) {
2502 if (itr.
index() < i->first) {
2505 if (i->second != j && itr.
index() == i->first && *itr != 0) {
2507 cerr <<
"tableau[i][base[j]], with i different from j, must be "
2518 if (tableau[i].
get(base[i]) == 0) {
2520 cerr <<
"tableau[i][base[i]] must not be a zero" << endl;
2529 if (tableau[i].
get(tableau_num_columns - 1) != 0) {
2531 cerr <<
"the last column of the tableau must contain only"
2546 using namespace IO_Operators;
2547 s <<
"\nexternal_space_dim: " << external_space_dim <<
" \n";
2548 s <<
"\ninternal_space_dim: " << internal_space_dim <<
" \n";
2552 s <<
"\ninput_cs( " << input_cs_size <<
" )\n";
2554 input_cs[i]->ascii_dump(s);
2557 s <<
"\ninherited_constraints: " << inherited_constraints
2560 s <<
"\nfirst_pending_constraint: " << first_pending_constraint
2563 s <<
"\ninput_obj_function\n";
2564 input_obj_function.ascii_dump(s);
2566 << ((opt_mode ==
MAXIMIZATION) ?
"MAXIMIZATION" :
"MINIMIZATION") <<
"\n";
2568 s <<
"\ninitialized: " << (initialized ?
"YES" :
"NO") <<
"\n";
2571 case PRICING_STEEPEST_EDGE_FLOAT:
2572 s <<
"PRICING_STEEPEST_EDGE_FLOAT";
2574 case PRICING_STEEPEST_EDGE_EXACT:
2575 s <<
"PRICING_STEEPEST_EDGE_EXACT";
2577 case PRICING_TEXTBOOK:
2578 s <<
"PRICING_TEXTBOOK";
2586 s <<
"UNSATISFIABLE";
2597 case PARTIALLY_SATISFIABLE:
2598 s <<
"PARTIALLY_SATISFIABLE";
2604 tableau.ascii_dump(s);
2605 s <<
"\nworking_cost( " << working_cost.size()<<
" )\n";
2606 working_cost.ascii_dump(s);
2609 s <<
"\nbase( " << base_size <<
" )\n";
2611 s << base[i] <<
' ';
2614 s <<
"\nlast_generator\n";
2615 last_generator.ascii_dump(s);
2618 s <<
"\nmapping( " << mapping_size <<
" )\n";
2620 s <<
"\n"<< i <<
" -> " << mapping[i].first <<
" -> " << mapping[i].second
2624 s <<
"\n\ninteger_variables";
2625 i_variables.ascii_dump(s);
2633 if (!(s >> str) || str !=
"external_space_dim:") {
2637 if (!(s >> external_space_dim)) {
2641 if (!(s >> str) || str !=
"internal_space_dim:") {
2645 if (!(s >> internal_space_dim)) {
2649 if (!(s >> str) || str !=
"input_cs(") {
2655 if (!(s >> input_cs_size)) {
2659 if (!(s >> str) || str !=
")") {
2664 input_cs.reserve(input_cs_size);
2669 add_constraint_helper(c);
2672 if (!(s >> str) || str !=
"inherited_constraints:") {
2676 if (!(s >> inherited_constraints)) {
2682 inherited_constraints = 0;
2684 if (!(s >> str) || str !=
"first_pending_constraint:") {
2687 if (!(s >> first_pending_constraint)) {
2690 if (!(s >> str) || str !=
"input_obj_function") {
2693 if (!input_obj_function.ascii_load(s)) {
2696 if (!(s >> str) || str !=
"opt_mode") {
2702 if (str ==
"MAXIMIZATION") {
2706 if (str !=
"MINIMIZATION") {
2712 if (!(s >> str) || str !=
"initialized:") {
2721 else if (str ==
"NO") {
2722 initialized =
false;
2728 if (!(s >> str) || str !=
"pricing:") {
2734 if (str ==
"PRICING_STEEPEST_EDGE_FLOAT") {
2735 pricing = PRICING_STEEPEST_EDGE_FLOAT;
2737 else if (str ==
"PRICING_STEEPEST_EDGE_EXACT") {
2738 pricing = PRICING_STEEPEST_EDGE_EXACT;
2740 else if (str ==
"PRICING_TEXTBOOK") {
2741 pricing = PRICING_TEXTBOOK;
2747 if (!(s >> str) || str !=
"status:") {
2755 if (str ==
"UNSATISFIABLE") {
2756 status = UNSATISFIABLE;
2758 else if (str ==
"SATISFIABLE") {
2759 status = SATISFIABLE;
2761 else if (str ==
"UNBOUNDED") {
2764 else if (str ==
"OPTIMIZED") {
2767 else if (str ==
"PARTIALLY_SATISFIABLE") {
2768 status = PARTIALLY_SATISFIABLE;
2774 if (!(s >> str) || str !=
"tableau") {
2778 if (!tableau.ascii_load(s)) {
2782 if (!(s >> str) || str !=
"working_cost(") {
2788 if (!(s >> working_cost_dim)) {
2792 if (!(s >> str) || str !=
")") {
2796 if (!working_cost.ascii_load(s)) {
2800 if (!(s >> str) || str !=
"base(") {
2805 if (!(s >> base_size)) {
2809 if (!(s >> str) || str !=
")") {
2815 if (!(s >> base_value)) {
2818 base.push_back(base_value);
2821 if (!(s >> str) || str !=
"last_generator") {
2825 if (!last_generator.ascii_load(s)) {
2829 if (!(s >> str) || str !=
"mapping(") {
2834 if (!(s >> mapping_size)) {
2837 if (!(s >> str) || str !=
")") {
2843 if (tableau.num_columns() != 0) {
2844 mapping.push_back(std::make_pair(0, 0));
2849 if (!(s >> index)) {
2853 if (!(s >> str) || str !=
"->") {
2858 if (!(s >> first_value)) {
2862 if (!(s >> str) || str !=
"->") {
2867 if (!(s >> second_value)) {
2871 mapping.push_back(std::make_pair(first_value, second_value));
2874 if (!(s >> str) || str !=
"integer_variables") {
2878 if (!i_variables.ascii_load(s)) {
2889 s <<
"Constraints:";
2894 s <<
"\nObjective function: "
2896 <<
"\nOptimization mode: "
Minimization is requested.
bool is_satisfiable() const
Checks satisfiability of *this.
dimension_type index() const
Returns the index of the element pointed to by *this.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
An iterator over a system of constraints.
void normalize()
Normalizes the modulo of coefficients so that they are mutually prime.
dimension_type space_dimension() const
Returns the dimension of the smallest vector space enclosing all the variables whose indexes are in t...
iterator find(dimension_type i)
Looks for an element with index i.
dimension_type max_space_dimension()
Returns the maximum space dimension this library can handle.
A linear equality or inequality.
const_iterator begin() const
bool is_equality() const
Returns true if and only if *this is an equality constraint.
void swap(CO_Tree &x, CO_Tree &y)
Optimization_Mode
Possible optimization modes.
void linear_combine(const Sparse_Row &y, Coefficient_traits::const_reference coeff1, Coefficient_traits::const_reference coeff2)
A finite sequence of coefficients.
size_t dimension_type
An unsigned integral type for representing space dimensions.
static void linear_combine(Row &x, const Row &y, const dimension_type k)
Linearly combines x with y so that *this[k] is 0.
bool ascii_load(std::istream &s)
Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this ...
An std::set of variables' indexes.
A line, ray, point or closure point.
Linear_Expression expr
The linear expression encoding *this.
void add_constraints(const Constraint_System &cs)
Adds a copy of the constraints in cs to the MIP problem.
void normalize()
Normalizes the modulo of coefficients so that they are mutually prime.
dimension_type size() const
Returns the size of the row.
void linear_combine(Dense_Row &x, const Dense_Row &y, Coefficient_traits::const_reference coeff1, Coefficient_traits::const_reference coeff2)
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
void m_swap(Sparse_Row &x)
Swaps *this and x.
const_iterator constraints_end() const
Returns a past-the-end read-only iterator to the sequence of constraints defining the feasible region...
bool is_in_base(dimension_type var_index, dimension_type &row_index) const
Enable_If< Is_Native_Or_Checked< T >::value, void >::type ascii_dump(std::ostream &s, const T &t)
dimension_type not_a_dimension()
Returns a value that does not designate a valid dimension.
void add_mul_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
std::ostream & operator<<(std::ostream &s, const Ask_Tell< D > &x)
void abs_assign(GMP_Integer &x)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
A finite sparse sequence of coefficients.
The standard C++ namespace.
void lcm_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
An iterator on the tree elements, ordered by key.
const iterator & end()
Returns an iterator that points after the last stored element.
A helper class to temporarily relax a MIP problem using RAII.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
std::vector< Constraint * > input_cs
The sequence of constraints describing the feasible region.
void evaluate_objective_function(const Generator &evaluating_point, Coefficient &numer, Coefficient &denom) const
Sets num and denom so that is the result of evaluating the objective function on evaluating_point...
#define WEIGHT_ADD(delta)
void add_constraint(const Constraint &c)
Adds a copy of constraint c to the MIP problem.
const_iterator begin() const
Returns the const_iterator pointing to the first constraint, if *this is not empty; otherwise...
void exact_div_assign(Checked_Number< T, Policy > &x, const Checked_Number< T, Policy > &y, const Checked_Number< T, Policy > &z)
Coefficient_traits::const_reference coefficient(Variable v) const
Returns the coefficient of v in *this.
A tag type to distinguish normal vs. inheriting copy constructor.
bool is_lp_satisfiable() const
Returns true if and if only the LP problem is satisfiable.
const Variables_Set & integer_space_dimensions() const
Returns a set containing all the variables' indexes constrained to be integral.
A read-only iterator on the constraints defining the feasible region.
void erase_artificials(dimension_type begin_artificials, dimension_type end_artificials)
Drop unnecessary artificial variables from the tableau and get ready for the second phase of the simp...
const Linear_Expression & objective_function() const
Returns the objective function.
const Generator & optimizing_point() const
Returns an optimal point for *this, if it exists.
std::vector< std::pair< dimension_type, dimension_type > > mapping
A map between the variables of `input_cs' and `tableau'.
dimension_type get_exiting_base_index(dimension_type entering_var_index) const
Computes the row index of the variable exiting the base of the MIP problem. Implemented with anti-cyc...
bool compute_simplex_using_steepest_edge_float()
Returns true if and if only the algorithm successfully computed a feasible solution.
A dimension of the vector space.
bool is_strict_inequality() const
Returns true if and only if *this is a strict inequality constraint.
Result assign(Boundary_Type to_type, To &to, To_Info &to_info, Boundary_Type type, const T &x, const Info &info, bool should_shrink=false)
Variables_Set i_variables
A set containing all the indexes of variables that are constrained to have an integer value...
dimension_type size() const
Gives the number of coefficients currently in use.
bool is_inequality() const
Returns true if and only if *this is an inequality constraint (either strict or non-strict).
A wrapper for numeric types implementing a given policy.
The problem is unbounded.
const_iterator constraints_begin() const
Returns a read-only iterator to the first constraint defining the feasible region.
Matrix< Row > tableau
The matrix encoding the current feasible region in tableau form.
bool is_canonical(const mpq_class &x)
Returns true if and only if x is in canonical form.
dimension_type steepest_edge_float_entering_index() const
Same as steepest_edge_exact_entering_index, but using floating points.
bool OK() const
Checks if all the invariants are satisfied.
Optimization_Mode optimization_mode() const
Returns the optimization mode.
dimension_type merge_split_variable(dimension_type var_index)
Merges back the positive and negative part of a (previously split) variable after detecting a corresp...
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
The problem is unfeasible.
static bool is_mip_satisfiable(MIP_Problem &mip, const Variables_Set &i_vars, Generator &p)
Returns true if and if only the MIP problem mip is satisfiable when variables in i_vars can only take...
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
const mpz_class & raw_value(const GMP_Integer &x)
void pivot(dimension_type entering_var_index, dimension_type exiting_base_index)
Performs the pivoting operation on the tableau.
const_iterator end() const
Returns the past-the-end const_iterator.
dimension_type steepest_edge_exact_entering_index() const
Computes the column index of the variable entering the base, using an exact steepest-edge algorithm w...
A Mixed Integer (linear) Programming problem.
const_iterator end() const
Iterator pointing after the last nonzero variable coefficient.
static bool choose_branching_variable(const MIP_Problem &mip, const Variables_Set &i_vars, dimension_type &branching_index)
Returns true if and if only mip.last_generator satisfies all the integrality conditions implicitly st...
#define WEIGHT_ADD_MUL(delta, factor)
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type ascii_load(std::istream &s, T &t)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
static bool is_satisfied(const Constraint &c, const Generator &g)
Returns true if and only if c is satisfied by g.
bool is_point() const
Returns true if and only if *this is a point.
static MIP_Problem_Status solve_mip(bool &have_incumbent_solution, mpq_class &incumbent_solution_value, Generator &incumbent_solution_point, MIP_Problem &mip, const Variables_Set &i_vars)
Returns a status that encodes the solution of the MIP problem.
#define PPL_DIRTY_TEMP(T, id)
bool initialized
A Boolean encoding whether or not internal data structures have already been properly sized and popul...
iterator insert(dimension_type i, Coefficient_traits::const_reference x)
Equivalent to (*this)[i] = x; find(i), but faster.
Status status
The internal state of the MIP problem.
void second_phase()
Optimizes the MIP problem using the second phase of the primal simplex algorithm. ...
static bool is_unbounded_obj_function(const Linear_Expression &obj_function, const std::vector< std::pair< dimension_type, dimension_type > > &mapping, Optimization_Mode optimization_mode)
void neg_assign(GMP_Integer &x)
dimension_type first_nonzero(dimension_type first, dimension_type last) const
#define PPL_OUTPUT_DEFINITIONS(class_name)
Generator point(const Linear_Expression &e=Linear_Expression::zero(), Coefficient_traits::const_reference d=Coefficient_one(), Representation r=Generator::default_representation)
Shorthand for Generator::point(const Linear_Expression& e, Coefficient_traits::const_reference d...
The entire library is confined to this namespace.
dimension_type textbook_entering_index() const
Computes the column index of the variable entering the base, using the textbook algorithm with anti-c...
A const iterator on the tree elements, ordered by key.
static bool is_saturated(const Constraint &c, const Generator &g)
Returns true if and only if c is saturated by g.
iterator lower_bound(dimension_type i)
Lower bound of index i.
const Generator & feasible_point() const
Returns a feasible point for *this, if it exists.
void insert(Variable v)
Inserts the index of variable v into the set.
void add_constraint_helper(const Constraint &c)
Helper method: implements exception safe addition.
Maximization is requested.
static const Constraint & zero_dim_positivity()
The true (zero-dimension space) constraint , also known as positivity constraint. ...
void set_objective_function(const Linear_Expression &obj)
Sets the objective function to obj.
iterator begin()
Returns an iterator that points at the first stored element.
Generator last_generator
The last successfully computed feasible or optimizing point.
int sgn_b(Boundary_Type type, const T &x, const Info &info)
MIP_Problem_Status solve() const
Optimizes the MIP problem.
dimension_type internal_space_dim
The space dimension of the current (partial) solution of the MIP problem; it may be smaller than exte...
base_type::const_iterator const_iterator
The type of const iterators on coefficients.
Coefficient_traits::const_reference coefficient(Variable v) const
Returns the coefficient of v in *this.
const_iterator end() const
void gcd_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
void compute_generator() const
Computes a valid generator that satisfies all the constraints of the Linear Programming problem assoc...
int sgn(Boundary_Type type, const T &x, const Info &info)
void sub_mul_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
bool parse_constraints(dimension_type &additional_tableau_rows, dimension_type &additional_slack_variables, std::deque< bool > &is_tableau_constraint, std::deque< bool > &is_satisfied_inequality, std::deque< bool > &is_nonnegative_variable, std::deque< bool > &is_remergeable_variable) const
Parses the pending constraints to gather information on how to resize the tableau.
void normalize2(Coefficient_traits::const_reference x, Coefficient_traits::const_reference y, Coefficient &n_x, Coefficient &n_y)
If is the GCD of x and y, the values of x and y divided by are assigned to n_x and n_y...
static int sign(const Linear_Expression &x, const Linear_Expression &y)
Returns the sign of the scalar product between x and y.
bool compute_simplex_using_exact_pricing()
Returns true if and if only the algorithm successfully computed a feasible solution.
void process_pending_constraints()
Processes the pending constraints of *this.
Coefficient_traits::const_reference divisor() const
If *this is either a point or a closure point, returns its divisor.
dimension_type external_space_dim
The dimension of the vector space.
Coefficient_traits::const_reference inhomogeneous_term() const
Returns the inhomogeneous term of *this.
void add_space_dimensions_and_embed(dimension_type m)
Adds m new space dimensions and embeds the old MIP problem in the new vector space.
Coefficient_traits::const_reference Coefficient_one()
Returns a const reference to a Coefficient with value 1.
expr_type expression() const
Partial read access to the (adapted) internal expression.
dimension_type index() const
Returns the index of the element pointed to by *this.
const_iterator begin() const
Iterator pointing to the first nonzero variable coefficient.
dimension_type first_pending_constraint
The first index of `input_cs' containing a pending constraint.
Coefficient_traits::const_reference get(dimension_type i) const
static dimension_type max_space_dimension()
Returns the maximum space dimension an MIP_Problem can handle.
Coefficient_traits::const_reference get(dimension_type i) const
Gets the i-th element in the sequence.
An adapter for Linear_Expression that maybe hides the last coefficient.
bool all_zeroes(const Variables_Set &vars) const
Returns true if the coefficient of each variable in vars is zero.
MIP_Problem(dimension_type dim=0)
Builds a trivial MIP problem.
The problem has an optimal solution.
MIP_Problem_Status
Possible outcomes of the MIP_Problem solver.
bool has_strict_inequalities() const
Returns true if and only if *this contains one or more strict inequality constraints.
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
void add_to_integer_space_dimensions(const Variables_Set &i_vars)
Sets the variables whose indexes are in set i_vars to be integer space dimensions.
dimension_type space_dimension() const
Returns the space dimension of the MIP problem.