235 const absl::flat_hash_set<RowId>& deleted_rows,
236 absl::Span<const RowId> new_rows,
237 const absl::flat_hash_set<ColumnId>& deleted_columns,
238 absl::Span<const ColumnId> new_columns,
239 const absl::flat_hash_set<std::pair<RowId, ColumnId>>& dirty)
const;
242 void CompactIfNeeded();
245 absl::flat_hash_map<std::pair<RowId, ColumnId>,
double> values_;
246 absl::flat_hash_map<RowId, std::vector<ColumnId>> rows_;
247 absl::flat_hash_map<ColumnId, std::vector<RowId>> columns_;
250 int64_t nonzeros_ = 0;
260template <
typename RowId,
typename ColumnId>
262 std::vector<std::tuple<RowId, ColumnId, double>> entries);
274template <
typename RowId,
typename ColumnId>
276 std::vector<std::tuple<RowId, ColumnId, double>> entries) {
277 absl::c_sort(entries);
278 const int num_entries =
static_cast<int>(entries.size());
283 for (
const auto [lin_con, var, coef] : entries) {
297std::pair<VariableId, VariableId> SparseSymmetricMatrix::make_key(
299 return {std::min(first, second), std::max(first, second)};
303 const double value) {
304 const std::pair<VariableId, VariableId> key = make_key(first, second);
305 auto map_iter = values_.find(key);
307 if (map_iter == values_.end()) {
311 related_variables_[first].push_back(second);
312 if (first != second) {
313 related_variables_[second].push_back(first);
315 values_[key] = value;
319 if (map_iter->second == value) {
322 const double old_value = map_iter->second;
323 map_iter->second = value;
327 }
else if (old_value == 0.0) {
343template <
typename RowId,
typename ColumnId>
345 const double value) {
346 const std::pair<RowId, ColumnId> key = {row, column};
347 const auto it = values_.find(key);
348 if (it == values_.end()) {
354 values_[key] = value;
358 if (it->second == value) {
361 const double old_value = it->second;
366 }
else if (old_value == 0.0) {
373template <
typename RowId,
typename ColumnId>
375 const ColumnId column)
const {
376 const auto it = values_.find({row, column});
377 if (it != values_.end()) {
382template <
typename RowId,
typename ColumnId>
384 const ColumnId
column)
const {
385 const auto it = values_.find({
row,
column});
386 return it != values_.end() && it->second != 0.0;
389template <
typename RowId,
typename ColumnId>
391 const auto row_it = rows_.find(
row);
392 if (row_it == rows_.end()) {
395 for (
const ColumnId col : row_it->second) {
396 auto val_it = values_.find({row_it->first, col});
397 if (val_it != values_.end() && val_it->second != 0.0) {
398 val_it->second = 0.0;
405template <
typename RowId,
typename ColumnId>
407 const auto col_it = columns_.find(column);
408 if (col_it == columns_.end()) {
411 for (
const RowId row : col_it->second) {
412 auto val_it = values_.find({row, col_it->first});
413 if (val_it != values_.end() && val_it->second != 0.0) {
414 val_it->second = 0.0;
421template <
typename RowId,
typename ColumnId>
423 const RowId row_id)
const {
424 std::vector<ColumnId> result;
425 const auto it = rows_.find(row_id);
426 if (it != rows_.end()) {
427 for (
const ColumnId col : it->second) {
428 if (contains(row_id, col)) {
429 result.push_back(col);
436template <
typename RowId,
typename ColumnId>
438 const ColumnId column_id)
const {
439 std::vector<RowId> result;
440 const auto it = columns_.find(column_id);
441 if (it != columns_.end()) {
442 for (
const RowId row_id : it->second) {
443 if (contains(row_id, column_id)) {
444 result.push_back(row_id);
451template <
typename RowId,
typename ColumnId>
452std::vector<std::pair<ColumnId, double>>
454 std::vector<std::pair<ColumnId, double>> result;
455 const auto it = rows_.find(row_id);
456 if (it != rows_.end()) {
457 for (
const ColumnId col : it->second) {
458 const double val = get(row_id, col);
460 result.push_back({col, val});
467template <
typename RowId,
typename ColumnId>
468std::vector<std::pair<RowId, double>>
470 std::vector<std::pair<RowId, double>> result;
471 const auto it = columns_.find(col_id);
472 if (it != columns_.end()) {
473 for (
const RowId row_id : it->second) {
474 const double val = get(row_id, col_id);
476 result.push_back({row_id, val});
483template <
typename RowId,
typename ColumnId>
484std::vector<std::tuple<RowId, ColumnId, double>>
486 std::vector<std::tuple<RowId, ColumnId, double>> result;
487 result.reserve(nonzeros_);
488 for (
const auto& [k, v] : values_) {
490 result.push_back({k.first, k.second, v});
496template <
typename RowId,
typename ColumnId>
503template <
typename RowId,
typename ColumnId>
508template <
typename RowId,
typename ColumnId>
511 std::vector<std::tuple<RowId, ColumnId, double>> terms = Terms();
513 for (
const auto [r,
c, v] : terms) {
521template <
typename RowId,
typename ColumnId>
523 const absl::flat_hash_set<RowId>& deleted_rows,
524 const absl::Span<const RowId> new_rows,
525 const absl::flat_hash_set<ColumnId>& deleted_columns,
526 const absl::Span<const ColumnId> new_columns,
527 const absl::flat_hash_set<std::pair<RowId, ColumnId>>& dirty)
const {
529 std::vector<std::tuple<LinearConstraintId, VariableId, double>>
536 if (deleted_rows.contains(
row) || deleted_columns.contains(
column)) {
542 for (
const ColumnId new_col : new_columns) {
544 for (
const auto [row, coef] : ColumnTerms(new_col)) {
545 matrix_updates.push_back({row, new_col, coef});
548 for (
const RowId new_row : new_rows) {
550 for (
const auto [col, coef] : RowTerms(new_row)) {
553 if (new_columns.empty() || col < new_columns[0]) {
554 matrix_updates.push_back({new_row, col, coef});
561template <
typename RowId,
typename ColumnId>
562void SparseMatrix<RowId, ColumnId>::CompactIfNeeded() {
563 const int64_t zeros = values_.size() - nonzeros_;
564 if (values_.empty() ||