// Copyright 2010-2021 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "ortools/lp_data/lp_utils.h" #include "ortools/lp_data/sparse_column.h" namespace operations_research { namespace glop { template Fractional SquaredNormTemplate(const SparseColumnLike& column) { Fractional sum(0.0); for (const SparseColumn::Entry e : column) { sum += Square(e.coefficient()); } return sum; } Fractional SquaredNorm(const SparseColumn& v) { return SquaredNormTemplate(v); } Fractional SquaredNorm(const ColumnView& v) { return SquaredNormTemplate(v); } Fractional PreciseSquaredNorm(const SparseColumn& v) { KahanSum sum; for (const SparseColumn::Entry e : v) { sum.Add(Square(e.coefficient())); } return sum.Value(); } Fractional PreciseSquaredNorm(const ScatteredColumn& v) { if (v.ShouldUseDenseIteration()) { return PreciseSquaredNorm(v.values); } KahanSum sum; for (const RowIndex row : v.non_zeros) { sum.Add(Square(v[row])); } return sum.Value(); } Fractional SquaredNorm(const DenseColumn& column) { Fractional sum(0.0); RowIndex row(0); const size_t num_blocks = column.size().value() / 4; for (size_t i = 0; i < num_blocks; ++i) { // See the comment in ScalarProduct in the header for some notes about the // effect of adding up several squares at a time. sum += Square(column[row++]) + Square(column[row++]) + Square(column[row++]) + Square(column[row++]); } while (row < column.size()) { sum += Square(column[row++]); } return sum; } Fractional PreciseSquaredNorm(const DenseColumn& column) { KahanSum sum; for (RowIndex row(0); row < column.size(); ++row) { sum.Add(Square(column[row])); } return sum.Value(); } Fractional InfinityNorm(const DenseColumn& v) { Fractional infinity_norm = 0.0; for (RowIndex row(0); row < v.size(); ++row) { infinity_norm = std::max(infinity_norm, fabs(v[row])); } return infinity_norm; } template Fractional InfinityNormTemplate(const SparseColumnLike& column) { Fractional infinity_norm = 0.0; for (const SparseColumn::Entry e : column) { infinity_norm = std::max(infinity_norm, fabs(e.coefficient())); } return infinity_norm; } Fractional InfinityNorm(const SparseColumn& v) { return InfinityNormTemplate(v); } Fractional InfinityNorm(const ColumnView& v) { return InfinityNormTemplate(v); } double Density(const DenseRow& row) { if (row.empty()) return 0.0; int sum = 0.0; for (ColIndex col(0); col < row.size(); ++col) { if (row[col] != Fractional(0.0)) ++sum; } return static_cast(sum) / row.size().value(); } void RemoveNearZeroEntries(Fractional threshold, DenseRow* row) { if (threshold == Fractional(0.0)) return; for (ColIndex col(0); col < row->size(); ++col) { if (fabs((*row)[col]) < threshold) { (*row)[col] = Fractional(0.0); } } } void RemoveNearZeroEntries(Fractional threshold, DenseColumn* column) { if (threshold == Fractional(0.0)) return; for (RowIndex row(0); row < column->size(); ++row) { if (fabs((*column)[row]) < threshold) { (*column)[row] = Fractional(0.0); } } } Fractional RestrictedInfinityNorm(const ColumnView& column, const DenseBooleanColumn& rows_to_consider, RowIndex* row_index) { Fractional infinity_norm = 0.0; for (const SparseColumn::Entry e : column) { if (rows_to_consider[e.row()] && fabs(e.coefficient()) > infinity_norm) { infinity_norm = fabs(e.coefficient()); *row_index = e.row(); } } return infinity_norm; } void SetSupportToFalse(const ColumnView& column, DenseBooleanColumn* b) { for (const SparseColumn::Entry e : column) { if (e.coefficient() != 0.0) { (*b)[e.row()] = false; } } } bool IsDominated(const ColumnView& column, const DenseColumn& radius) { for (const SparseColumn::Entry e : column) { DCHECK_GE(radius[e.row()], 0.0); if (fabs(e.coefficient()) > radius[e.row()]) return false; } return true; } } // namespace glop } // namespace operations_research