|
8 | 8 | #include <cuopt/error.hpp> |
9 | 9 | #include <cuopt/mathematical_optimization/cpu_optimization_problem.hpp> |
10 | 10 | #include <cuopt/mathematical_optimization/csr_matrix_utils.hpp> |
| 11 | +#include <cuopt/mathematical_optimization/io/mps_data_model.hpp> |
11 | 12 | #include <cuopt/mathematical_optimization/optimization_problem.hpp> |
12 | 13 | #include <cuopt/mathematical_optimization/optimization_problem_utils.hpp> |
13 | 14 | #include <cuopt/mathematical_optimization/solve_remote.hpp> |
|
25 | 26 |
|
26 | 27 | namespace cuopt::mathematical_optimization { |
27 | 28 |
|
| 29 | +namespace { |
| 30 | + |
| 31 | +// Classify a problem as LP / MIP / IP from its (enum) variable types. Single source of truth |
| 32 | +// shared by set_variable_types() and adopt_from_mps_data_model() so the detection rule lives in |
| 33 | +// one place. Empty types (no variables declared) classify as LP, matching the populate path where |
| 34 | +// set_variable_types() is skipped and the category keeps its LP default. |
| 35 | +problem_category_t problem_category_from_variable_types(const std::vector<var_t>& variable_types) |
| 36 | +{ |
| 37 | + if (variable_types.empty()) { return problem_category_t::LP; } |
| 38 | + const std::size_t n_discrete = static_cast<std::size_t>( |
| 39 | + std::count_if(variable_types.begin(), variable_types.end(), [](var_t v) { |
| 40 | + return v == var_t::INTEGER || v == var_t::SEMI_CONTINUOUS; |
| 41 | + })); |
| 42 | + if (n_discrete == variable_types.size()) { return problem_category_t::IP; } |
| 43 | + if (n_discrete > 0) { return problem_category_t::MIP; } |
| 44 | + return problem_category_t::LP; |
| 45 | +} |
| 46 | + |
| 47 | +} // namespace |
| 48 | + |
28 | 49 | // ============================================================================== |
29 | 50 | // Constructor |
30 | 51 | // ============================================================================== |
@@ -210,18 +231,7 @@ void cpu_optimization_problem_t<i_t, f_t>::set_variable_types(const var_t* varia |
210 | 231 | variable_types_.resize(size); |
211 | 232 | std::copy(variable_types, variable_types + size, variable_types_.begin()); |
212 | 233 |
|
213 | | - // Auto-detect problem category based on variable types (matching original optimization_problem_t) |
214 | | - i_t n_discrete = std::count_if(variable_types_.begin(), variable_types_.end(), [](auto val) { |
215 | | - return val == var_t::INTEGER || val == var_t::SEMI_CONTINUOUS; |
216 | | - }); |
217 | | - // By default it is LP |
218 | | - if (n_discrete == size) { |
219 | | - problem_category_ = problem_category_t::IP; |
220 | | - } else if (n_discrete > 0) { |
221 | | - problem_category_ = problem_category_t::MIP; |
222 | | - } else { |
223 | | - problem_category_ = problem_category_t::LP; |
224 | | - } |
| 234 | + problem_category_ = problem_category_from_variable_types(variable_types_); |
225 | 235 | } |
226 | 236 |
|
227 | 237 | template <typename i_t, typename f_t> |
@@ -1095,6 +1105,83 @@ void cpu_optimization_problem_t<i_t, f_t>::copy_variable_types_to_host(var_t* ou |
1095 | 1105 | std::copy(variable_types_.begin(), variable_types_.begin() + size, output); |
1096 | 1106 | } |
1097 | 1107 |
|
| 1108 | +// ============================================================================== |
| 1109 | +// adopt_from_mps_data_model |
| 1110 | +// ============================================================================== |
| 1111 | + |
| 1112 | +namespace { |
| 1113 | + |
| 1114 | +template <typename i_t, typename f_t> |
| 1115 | +void move_quadratic_constraints_from_model( |
| 1116 | + cpu_optimization_problem_t<i_t, f_t>& problem, |
| 1117 | + std::vector<typename io::mps_data_model_t<i_t, f_t>::quadratic_constraint_t>& model_constraints) |
| 1118 | +{ |
| 1119 | + using model_qc_t = typename io::mps_data_model_t<i_t, f_t>::quadratic_constraint_t; |
| 1120 | + std::vector<typename cpu_optimization_problem_t<i_t, f_t>::quadratic_constraint_t> converted; |
| 1121 | + converted.reserve(model_constraints.size()); |
| 1122 | + for (model_qc_t& qc : model_constraints) { |
| 1123 | + converted.push_back({qc.constraint_row_index, |
| 1124 | + std::move(qc.constraint_row_name), |
| 1125 | + qc.constraint_row_type, |
| 1126 | + std::move(qc.linear_values), |
| 1127 | + std::move(qc.linear_indices), |
| 1128 | + qc.rhs_value, |
| 1129 | + std::move(qc.rows), |
| 1130 | + std::move(qc.cols), |
| 1131 | + std::move(qc.vals)}); |
| 1132 | + } |
| 1133 | + model_constraints.clear(); |
| 1134 | + problem.set_quadratic_constraints(std::move(converted)); |
| 1135 | +} |
| 1136 | + |
| 1137 | +} // namespace |
| 1138 | + |
| 1139 | +template <typename i_t, typename f_t> |
| 1140 | +void cpu_optimization_problem_t<i_t, f_t>::adopt_from_mps_data_model( |
| 1141 | + io::mps_data_model_t<i_t, f_t>&& model) |
| 1142 | +{ |
| 1143 | + maximize_ = model.maximize_; |
| 1144 | + n_vars_ = model.n_vars_; |
| 1145 | + n_constraints_ = model.n_constraints_; |
| 1146 | + objective_scaling_factor_ = model.objective_scaling_factor_; |
| 1147 | + objective_offset_ = model.objective_offset_; |
| 1148 | + |
| 1149 | + A_ = std::move(model.A_); |
| 1150 | + A_indices_ = std::move(model.A_indices_); |
| 1151 | + A_offsets_ = std::move(model.A_offsets_); |
| 1152 | + b_ = std::move(model.b_); |
| 1153 | + c_ = std::move(model.c_); |
| 1154 | + constraint_lower_bounds_ = std::move(model.constraint_lower_bounds_); |
| 1155 | + constraint_upper_bounds_ = std::move(model.constraint_upper_bounds_); |
| 1156 | + row_types_ = std::move(model.row_types_); |
| 1157 | + variable_lower_bounds_ = std::move(model.variable_lower_bounds_); |
| 1158 | + variable_upper_bounds_ = std::move(model.variable_upper_bounds_); |
| 1159 | + |
| 1160 | + objective_name_ = std::move(model.objective_name_); |
| 1161 | + problem_name_ = std::move(model.problem_name_); |
| 1162 | + var_names_ = std::move(model.var_names_); |
| 1163 | + row_names_ = std::move(model.row_names_); |
| 1164 | + |
| 1165 | + Q_values_ = std::move(model.Q_objective_values_); |
| 1166 | + Q_indices_ = std::move(model.Q_objective_indices_); |
| 1167 | + Q_offsets_ = std::move(model.Q_objective_offsets_); |
| 1168 | + |
| 1169 | + variable_types_.resize(model.var_types_.size()); |
| 1170 | + for (size_t i = 0; i < model.var_types_.size(); ++i) { |
| 1171 | + variable_types_[i] = char_to_var_type(model.var_types_[i]); |
| 1172 | + } |
| 1173 | + problem_category_ = problem_category_from_variable_types(variable_types_); |
| 1174 | + |
| 1175 | + if (model.has_quadratic_constraints()) { |
| 1176 | + move_quadratic_constraints_from_model(*this, model.quadratic_constraints_); |
| 1177 | + } |
| 1178 | + |
| 1179 | + model.var_types_.clear(); |
| 1180 | + model.n_vars_ = 0; |
| 1181 | + model.n_constraints_ = 0; |
| 1182 | + model.nnz_ = 0; |
| 1183 | +} |
| 1184 | + |
1098 | 1185 | // ============================================================================== |
1099 | 1186 | // Template instantiations matching optimization_problem_t |
1100 | 1187 | // ============================================================================== |
|
0 commit comments