| 524 | } |
| 525 | |
| 526 | HighsStatus Highs::addRowsInterface(HighsInt ext_num_new_row, |
| 527 | const double* ext_row_lower, |
| 528 | const double* ext_row_upper, |
| 529 | HighsInt ext_num_new_nz, |
| 530 | const HighsInt* ext_ar_start, |
| 531 | const HighsInt* ext_ar_index, |
| 532 | const double* ext_ar_value) { |
| 533 | // addRows is fundamentally different from addCols, since the new |
| 534 | // matrix data are held row-wise, so we have to insert data into the |
| 535 | // column-wise matrix of the LP. |
| 536 | if (kExtendInvertWhenAddingRows) { |
| 537 | if (ekk_instance_.status_.has_nla) |
| 538 | ekk_instance_.debugNlaCheckInvert("Start of Highs::addRowsInterface", |
| 539 | kHighsDebugLevelExpensive + 1); |
| 540 | } |
| 541 | HighsStatus return_status = HighsStatus::kOk; |
| 542 | HighsOptions& options = options_; |
| 543 | if (ext_num_new_row < 0) return HighsStatus::kError; |
| 544 | if (ext_num_new_nz < 0) return HighsStatus::kError; |
| 545 | if (ext_num_new_row == 0) return HighsStatus::kOk; |
| 546 | if (ext_num_new_row > 0) |
| 547 | if (isRowDataNull(options.log_options, ext_row_lower, ext_row_upper)) |
| 548 | return HighsStatus::kError; |
| 549 | if (ext_num_new_nz > 0) |
| 550 | if (isMatrixDataNull(options.log_options, ext_ar_start, ext_ar_index, |
| 551 | ext_ar_value)) |
| 552 | return HighsStatus::kError; |
| 553 | |
| 554 | HighsLp& lp = model_.lp_; |
| 555 | HighsBasis& basis = basis_; |
| 556 | HighsScale& scale = lp.scale_; |
| 557 | bool& useful_basis = basis.useful; |
| 558 | |
| 559 | bool& lp_has_scaling = lp.scale_.has_scaling; |
| 560 | |
| 561 | // Check that if nonzeros are to be added then the model has a positive number |
| 562 | // of columns |
| 563 | if (lp.num_col_ <= 0 && ext_num_new_nz > 0) return HighsStatus::kError; |
| 564 | |
| 565 | // Record the new number of rows |
| 566 | HighsInt newNumRow = lp.num_row_ + ext_num_new_row; |
| 567 | |
| 568 | HighsIndexCollection index_collection; |
| 569 | index_collection.dimension_ = ext_num_new_row; |
| 570 | index_collection.is_interval_ = true; |
| 571 | index_collection.from_ = 0; |
| 572 | index_collection.to_ = ext_num_new_row - 1; |
| 573 | // Take a copy of the bounds that can be normalised |
| 574 | std::vector<double> local_rowLower{ext_row_lower, |
| 575 | ext_row_lower + ext_num_new_row}; |
| 576 | std::vector<double> local_rowUpper{ext_row_upper, |
| 577 | ext_row_upper + ext_num_new_row}; |
| 578 | |
| 579 | return_status = interpretCallStatus( |
| 580 | options_.log_options, |
| 581 | assessBounds(options, "Row", lp.num_row_, index_collection, |
| 582 | local_rowLower, local_rowUpper, options.infinite_bound), |
| 583 | return_status, "assessBounds"); |
nothing calls this directly
no test coverage detected