| 1455 | } |
| 1456 | |
| 1457 | void HighsSparseMatrix::priceByRowWithSwitch( |
| 1458 | const bool quad_precision, HVector& result, const HVector& column, |
| 1459 | const double expected_density, const HighsInt from_index, |
| 1460 | const double switch_density, const HighsInt debug_report) const { |
| 1461 | assert(this->isRowwise()); |
| 1462 | HighsSparseVectorSum sum; |
| 1463 | // todo @Julian: Setting up the sparse vector sum is equivalent to calling |
| 1464 | // HVector::setup() I think there should instead be overloads where the result |
| 1465 | // vector is of type HVectorQuad for the future and not the boolean parameter |
| 1466 | // quad_precision. Then the buffer can be maintained similar to row_ap. |
| 1467 | if (quad_precision) sum.setDimension(num_col_); |
| 1468 | if (debug_report >= kDebugReportAll) |
| 1469 | printf("\nHighsSparseMatrix::priceByRowWithSwitch\n"); |
| 1470 | // (Continue) hyper-sparse row-wise PRICE with possible switches to |
| 1471 | // standard row-wise PRICE either immediately based on historical |
| 1472 | // density or during hyper-sparse PRICE if there is too much fill-in |
| 1473 | HighsInt next_index = from_index; |
| 1474 | // Possibly don't perform hyper-sparse PRICE based on historical density |
| 1475 | // |
| 1476 | // Ensure that result was set up for this number of columns, and |
| 1477 | // that result.index is still of correct size |
| 1478 | assert(HighsInt(result.size) == this->num_col_); |
| 1479 | assert(HighsInt(result.index.size()) == this->num_col_); |
| 1480 | if (expected_density <= kHyperPriceDensity) { |
| 1481 | double inv_num_col = 1.0 / this->num_col_; |
| 1482 | for (HighsInt ix = next_index; ix < column.count; ix++) { |
| 1483 | HighsInt iRow = column.index[ix]; |
| 1484 | // Determine whether p_end_ or the next start_ ends the loop |
| 1485 | HighsInt to_iEl; |
| 1486 | if (this->format_ == MatrixFormat::kRowwisePartitioned) { |
| 1487 | to_iEl = this->p_end_[iRow]; |
| 1488 | } else { |
| 1489 | to_iEl = this->start_[iRow + 1]; |
| 1490 | } |
| 1491 | // Possibly switch to standard row-wise price |
| 1492 | HighsInt row_num_nz = to_iEl - this->start_[iRow]; |
| 1493 | double local_density = (1.0 * result.count) * inv_num_col; |
| 1494 | bool switch_to_dense = result.count + row_num_nz >= this->num_col_ || |
| 1495 | local_density > switch_density; |
| 1496 | if (switch_to_dense) break; |
| 1497 | double multiplier = column.array[iRow]; |
| 1498 | if (debug_report == kDebugReportAll || debug_report == iRow) |
| 1499 | debugReportRowPrice(iRow, multiplier, to_iEl, result.array); |
| 1500 | if (multiplier) { |
| 1501 | if (quad_precision) { |
| 1502 | for (HighsInt iEl = this->start_[iRow]; iEl < to_iEl; iEl++) { |
| 1503 | sum.add(this->index_[iEl], multiplier * this->value_[iEl]); |
| 1504 | } |
| 1505 | } else { |
| 1506 | for (HighsInt iEl = this->start_[iRow]; iEl < to_iEl; iEl++) { |
| 1507 | HighsInt iCol = this->index_[iEl]; |
| 1508 | double value0 = result.array[iCol]; |
| 1509 | double value1 = value0 + multiplier * this->value_[iEl]; |
| 1510 | if (value0 == 0) result.index[result.count++] = iCol; |
| 1511 | result.array[iCol] = |
| 1512 | (fabs(value1) < kHighsTiny) ? kHighsZero : value1; |
| 1513 | } |
| 1514 | } |
no test coverage detected