| 2395 | } |
| 2396 | |
| 2397 | HighsStatus Highs::getReducedRow(const HighsInt row, double* row_vector, |
| 2398 | HighsInt* row_num_nz, HighsInt* row_indices, |
| 2399 | const double* pass_basis_inverse_row_vector) { |
| 2400 | HighsLp& lp = model_.lp_; |
| 2401 | // Ensure that the LP is column-wise |
| 2402 | lp.ensureColwise(); |
| 2403 | if (row_vector == NULL) { |
| 2404 | highsLogUser(options_.log_options, HighsLogType::kError, |
| 2405 | "getReducedRow: row_vector is NULL\n"); |
| 2406 | return HighsStatus::kError; |
| 2407 | } |
| 2408 | // row_indices can be NULL - it's the trigger that determines |
| 2409 | // whether they are identified or not pass_basis_inverse_row_vector |
| 2410 | // NULL - it's the trigger to determine whether it's computed or not |
| 2411 | if (row < 0 || row >= lp.num_row_) { |
| 2412 | highsLogUser(options_.log_options, HighsLogType::kError, |
| 2413 | "Row index %" HIGHSINT_FORMAT |
| 2414 | " out of range [0, %" HIGHSINT_FORMAT "] in getReducedRow\n", |
| 2415 | row, lp.num_row_ - 1); |
| 2416 | return HighsStatus::kError; |
| 2417 | } |
| 2418 | if (!ekk_instance_.status_.has_invert) |
| 2419 | return invertRequirementError("getReducedRow"); |
| 2420 | HighsInt num_row = lp.num_row_; |
| 2421 | vector<double> basis_inverse_row; |
| 2422 | double* basis_inverse_row_vector = (double*)pass_basis_inverse_row_vector; |
| 2423 | if (basis_inverse_row_vector == NULL) { |
| 2424 | vector<double> rhs; |
| 2425 | vector<HighsInt> col_indices; |
| 2426 | rhs.assign(num_row, 0); |
| 2427 | rhs[row] = 1; |
| 2428 | basis_inverse_row.resize(num_row, 0); |
| 2429 | // Form B^{-T}e_{row} |
| 2430 | basisSolveInterface(rhs, basis_inverse_row.data(), NULL, NULL, true); |
| 2431 | basis_inverse_row_vector = basis_inverse_row.data(); |
| 2432 | } |
| 2433 | bool return_indices = row_num_nz != NULL; |
| 2434 | if (return_indices) *row_num_nz = 0; |
| 2435 | for (HighsInt col = 0; col < lp.num_col_; col++) { |
| 2436 | double value = 0; |
| 2437 | for (HighsInt el = lp.a_matrix_.start_[col]; |
| 2438 | el < lp.a_matrix_.start_[col + 1]; el++) { |
| 2439 | HighsInt row = lp.a_matrix_.index_[el]; |
| 2440 | value += lp.a_matrix_.value_[el] * basis_inverse_row_vector[row]; |
| 2441 | } |
| 2442 | row_vector[col] = 0; |
| 2443 | if (fabs(value) > kHighsTiny) { |
| 2444 | if (return_indices) row_indices[(*row_num_nz)++] = col; |
| 2445 | row_vector[col] = value; |
| 2446 | } |
| 2447 | } |
| 2448 | return HighsStatus::kOk; |
| 2449 | } |
| 2450 | |
| 2451 | HighsStatus Highs::getReducedColumn(const HighsInt col, double* col_vector, |
| 2452 | HighsInt* col_num_nz, |