| 6474 | } |
| 6475 | |
| 6476 | HPresolve::Result HPresolve::removeDependentEquations( |
| 6477 | HighsPostsolveStack& postsolve_stack) { |
| 6478 | assert(analysis_.allow_rule_[kPresolveRuleDependentEquations]); |
| 6479 | const bool logging_on = analysis_.logging_on_; |
| 6480 | if (equations.empty()) return Result::kOk; |
| 6481 | |
| 6482 | if (logging_on) |
| 6483 | analysis_.startPresolveRuleLog(kPresolveRuleDependentEquations); |
| 6484 | |
| 6485 | HighsSparseMatrix matrix; |
| 6486 | matrix.num_col_ = equations.size(); |
| 6487 | matrix.num_row_ = model->num_col_ + 1; |
| 6488 | matrix.start_.resize(matrix.num_col_ + 1); |
| 6489 | matrix.start_[0] = 0; |
| 6490 | const HighsInt maxCapacity = numNonzeros() + matrix.num_col_; |
| 6491 | matrix.value_.reserve(maxCapacity); |
| 6492 | matrix.index_.reserve(maxCapacity); |
| 6493 | |
| 6494 | std::vector<HighsInt> eqSet(matrix.num_col_); |
| 6495 | HighsInt i = 0; |
| 6496 | for (const std::pair<HighsInt, HighsInt>& p : equations) { |
| 6497 | HighsInt eq = p.second; |
| 6498 | eqSet[i++] = eq; |
| 6499 | |
| 6500 | // add entries of equation |
| 6501 | for (const HighsSliceNonzero& nonz : getRowVector(eq)) { |
| 6502 | matrix.value_.push_back(nonz.value()); |
| 6503 | matrix.index_.push_back(nonz.index()); |
| 6504 | } |
| 6505 | |
| 6506 | // add entry for artificial rhs column |
| 6507 | if (model->row_lower_[eq] != 0.0) { |
| 6508 | matrix.value_.push_back(model->row_lower_[eq]); |
| 6509 | matrix.index_.push_back(model->num_col_); |
| 6510 | } |
| 6511 | |
| 6512 | matrix.start_[i] = matrix.value_.size(); |
| 6513 | } |
| 6514 | std::vector<HighsInt> colSet(matrix.num_col_); |
| 6515 | std::iota(colSet.begin(), colSet.end(), 0); |
| 6516 | HFactor factor; |
| 6517 | factor.setup(matrix, colSet); |
| 6518 | // Set up a time limit to prevent the redundant rows factorization |
| 6519 | // taking forever. |
| 6520 | // |
| 6521 | // Allow no more than 1% of the time limit to be spent on removing |
| 6522 | // dependent equations, but ensure that there is some limit since |
| 6523 | // options->time_limit is infinity by default |
| 6524 | // |
| 6525 | // ToDo: This is strictly non-deterministic, but so conservative |
| 6526 | // that it'll only reap the cases when factor.build never finishes |
| 6527 | const double time_limit = |
| 6528 | std::max(1.0, std::min(0.01 * options->time_limit, 1000.0)); |
| 6529 | factor.setTimeLimit(time_limit); |
| 6530 | const bool silent = silentLog(); |
| 6531 | // Determine rank deficiency of the equations |
| 6532 | if (!silent) |
| 6533 | highsLogUser(options->log_options, HighsLogType::kInfo, |
nothing calls this directly
no test coverage detected