| 244 | } |
| 245 | |
| 246 | void writeModelSolution(FILE* file, const HighsLogOptions& log_options, |
| 247 | const HighsModel& model, const HighsSolution& solution, |
| 248 | const HighsInfo& info, const bool sparse) { |
| 249 | const HighsLp& lp = model.lp_; |
| 250 | const bool have_primal = solution.value_valid; |
| 251 | const bool have_dual = solution.dual_valid; |
| 252 | assert(lp.col_names_.size() == static_cast<size_t>(lp.num_col_)); |
| 253 | assert(lp.row_names_.size() == static_cast<size_t>(lp.num_row_)); |
| 254 | if (have_primal) { |
| 255 | assert((int)solution.col_value.size() >= lp.num_col_); |
| 256 | assert((int)solution.row_value.size() >= lp.num_row_); |
| 257 | assert(info.primal_solution_status != kSolutionStatusNone); |
| 258 | } |
| 259 | if (have_dual) { |
| 260 | assert((int)solution.col_dual.size() >= lp.num_col_); |
| 261 | assert((int)solution.row_dual.size() >= lp.num_row_); |
| 262 | assert(info.dual_solution_status != kSolutionStatusNone); |
| 263 | } |
| 264 | std::stringstream ss; |
| 265 | highsFprintfString(file, log_options, "\n# Primal solution values\n"); |
| 266 | if (!have_primal || info.primal_solution_status == kSolutionStatusNone) { |
| 267 | highsFprintfString(file, log_options, "None\n"); |
| 268 | } else { |
| 269 | if (info.primal_solution_status == kSolutionStatusFeasible) { |
| 270 | highsFprintfString(file, log_options, "Feasible\n"); |
| 271 | } else { |
| 272 | assert(info.primal_solution_status == kSolutionStatusInfeasible); |
| 273 | highsFprintfString(file, log_options, "Infeasible\n"); |
| 274 | } |
| 275 | writeModelObjective(file, log_options, model, solution.col_value); |
| 276 | writePrimalSolution(file, log_options, model.lp_, solution.col_value, |
| 277 | sparse); |
| 278 | if (sparse) return; |
| 279 | ss.str(std::string()); |
| 280 | ss << highsFormatToString("# Rows %" HIGHSINT_FORMAT "\n", lp.num_row_); |
| 281 | highsFprintfString(file, log_options, ss.str()); |
| 282 | for (HighsInt ix = 0; ix < lp.num_row_; ix++) { |
| 283 | auto valStr = highsDoubleToString(solution.row_value[ix], |
| 284 | kHighsSolutionValueToStringTolerance); |
| 285 | ss.str(std::string()); |
| 286 | ss << highsFormatToString("%-s %s\n", lp.row_names_[ix].c_str(), |
| 287 | valStr.data()); |
| 288 | highsFprintfString(file, log_options, ss.str()); |
| 289 | } |
| 290 | } |
| 291 | highsFprintfString(file, log_options, "\n# Dual solution values\n"); |
| 292 | if (!have_dual || info.dual_solution_status == kSolutionStatusNone) { |
| 293 | highsFprintfString(file, log_options, "None\n"); |
| 294 | } else { |
| 295 | if (info.dual_solution_status == kSolutionStatusFeasible) { |
| 296 | highsFprintfString(file, log_options, "Feasible\n"); |
| 297 | } else { |
| 298 | assert(info.dual_solution_status == kSolutionStatusInfeasible); |
| 299 | highsFprintfString(file, log_options, "Infeasible\n"); |
| 300 | } |
| 301 | ss.str(std::string()); |
| 302 | ss << highsFormatToString("# Columns %" HIGHSINT_FORMAT "\n", lp.num_col_); |
| 303 | highsFprintfString(file, log_options, ss.str()); |
no test coverage detected