30 #ifndef OR_TOOLS_LP_DATA_SPARSE_VECTOR_H_ 31 #define OR_TOOLS_LP_DATA_SPARSE_VECTOR_H_ 38 #include "absl/strings/str_format.h" 49 template <
typename IndexType>
81 template <
typename IndexType,
101 #if !defined(_MSC_VER) 106 #if !defined(_MSC_VER) 134 void Reserve(EntryIndex new_capacity);
303 return ::util::IntegerRange<EntryIndex>(EntryIndex(0),
num_entries_);
394 void AddMultipleToSparseVectorInternal(
410 template <
typename IndexType>
445 template <
typename IndexType,
typename IteratorType>
447 return Iterator(this->index_, this->coefficient_, EntryIndex(0));
450 template <
typename IndexType,
typename IteratorType>
452 return Iterator(this->index_, this->coefficient_, num_entries_);
458 template <
typename IndexType,
typename IteratorType>
463 coefficient_(nullptr),
464 may_contain_duplicates_(false) {}
466 template <
typename IndexType,
typename IteratorType>
468 PopulateFromSparseVector(other);
471 template <
typename IndexType,
typename IteratorType>
474 PopulateFromSparseVector(other);
478 template <
typename IndexType,
typename IteratorType>
480 num_entries_ = EntryIndex(0);
481 may_contain_duplicates_ =
false;
484 template <
typename IndexType,
typename IteratorType>
486 capacity_ = EntryIndex(0);
487 num_entries_ = EntryIndex(0);
489 coefficient_ =
nullptr;
491 may_contain_duplicates_ =
false;
494 template <
typename IndexType,
typename IteratorType>
496 if (new_capacity <= capacity_)
return;
500 if (new_capacity.value() & 3) {
501 new_capacity += EntryIndex(4 - (new_capacity.value() & 3));
504 const size_t index_buffer_size = new_capacity.value() *
sizeof(
Index);
505 const size_t value_buffer_size = new_capacity.value() *
sizeof(
Fractional);
506 const size_t new_buffer_size = index_buffer_size + value_buffer_size;
507 std::unique_ptr<char[]> new_buffer(
new char[new_buffer_size]);
508 IndexType*
const new_index = reinterpret_cast<Index*>(new_buffer.get());
510 reinterpret_cast<Fractional*>(new_index + new_capacity.value());
513 if (num_entries_ > 0) {
518 std::memmove(new_index, index_,
sizeof(IndexType) * num_entries_.value());
519 std::memmove(new_coefficient, coefficient_,
524 coefficient_ = new_coefficient;
525 capacity_ = new_capacity;
528 template <
typename IndexType,
typename IteratorType>
530 return num_entries_ == EntryIndex(0);
533 template <
typename IndexType,
typename IteratorType>
543 template <
typename IndexType,
typename IteratorType>
555 std::vector<std::pair<Index, Fractional>> entries;
556 entries.reserve(num_entries_.value());
557 for (EntryIndex i(0); i < num_entries_; ++i) {
561 entries.begin(), entries.end(),
562 [](
const std::pair<Index, Fractional>&
a,
563 const std::pair<Index, Fractional>&
b) {
return a.first <
b.first; });
565 EntryIndex new_size(0);
566 for (
int i = 0; i < num_entries_; ++i) {
567 const std::pair<Index, Fractional> entry = entries[i];
568 if (entry.second == 0.0)
continue;
569 if (i + 1 == num_entries_ || entry.first != entries[i + 1].first) {
570 MutableIndex(new_size) = entry.first;
571 MutableCoefficient(new_size) = entry.second;
575 ResizeDown(new_size);
576 may_contain_duplicates_ =
false;
579 template <
typename IndexType,
typename IteratorType>
581 Index previous_index(-1);
582 for (
const EntryIndex i : AllEntryIndices()) {
585 previous_index =
index;
587 may_contain_duplicates_ =
false;
591 template <
typename IndexType,
typename IteratorType>
608 std::memmove(index_, sparse_vector.
index_,
617 template <
typename IndexType,
typename IteratorType>
621 const Index num_indices(dense_vector.
size());
623 if (dense_vector[
index] != 0.0) {
627 may_contain_duplicates_ =
false;
630 template <
typename IndexType,
typename IteratorType>
638 may_contain_duplicates_ =
true;
641 template <
typename IndexType,
typename IteratorType>
647 if (!may_contain_duplicates_ || num_entries_ <= 1)
return true;
650 const Index max_index =
651 *std::max_element(index_, index_ + num_entries_.value());
652 if (boolean_vector->
size() <= max_index) {
653 boolean_vector->
resize(max_index + 1,
false);
656 may_contain_duplicates_ =
false;
657 for (
const EntryIndex i : AllEntryIndices()) {
659 if ((*boolean_vector)[
index]) {
660 may_contain_duplicates_ =
true;
663 (*boolean_vector)[
index] =
true;
667 for (
const EntryIndex i : AllEntryIndices()) {
668 (*boolean_vector)[GetIndex(i)] =
false;
670 return !may_contain_duplicates_;
673 template <
typename IndexType,
typename IteratorType>
677 if (!may_contain_duplicates_ || num_entries_ <= 1)
return true;
679 return CheckNoDuplicates(&boolean_vector);
684 template <
typename IndexType,
typename IteratorType>
688 may_contain_duplicates_ =
true;
691 template <
typename IndexType,
typename IteratorType>
693 DCHECK(CheckNoDuplicates());
696 while (i < end && GetIndex(i) !=
index) {
699 if (i == end)
return;
700 const int num_moved_entries = (num_entries_ - i).
value() - 1;
701 std::memmove(index_ + i.value(), index_ + i.value() + 1,
702 sizeof(
Index) * num_moved_entries);
703 std::memmove(coefficient_ + i.value(), coefficient_ + i.value() + 1,
708 template <
typename IndexType,
typename IteratorType>
711 DCHECK(CheckNoDuplicates());
712 EntryIndex new_index(0);
713 for (
const EntryIndex i : AllEntryIndices()) {
715 if (magnitude > threshold) {
716 MutableIndex(new_index) = GetIndex(i);
721 ResizeDown(new_index);
724 template <
typename IndexType,
typename IteratorType>
727 DCHECK(CheckNoDuplicates());
728 EntryIndex new_index(0);
729 for (
const EntryIndex i : AllEntryIndices()) {
731 MutableIndex(new_index) = GetIndex(i);
736 ResizeDown(new_index);
739 template <
typename IndexType,
typename IteratorType>
742 DCHECK(CheckNoDuplicates());
743 for (
const EntryIndex i : AllEntryIndices()) {
744 if (GetIndex(i) ==
index) {
745 std::swap(MutableIndex(EntryIndex(0)), MutableIndex(i));
746 std::swap(MutableCoefficient(EntryIndex(0)), MutableCoefficient(i));
752 template <
typename IndexType,
typename IteratorType>
755 DCHECK(CheckNoDuplicates());
757 for (
const EntryIndex i : AllEntryIndices()) {
758 if (GetIndex(i) ==
index) {
759 std::swap(MutableIndex(last_entry), MutableIndex(i));
760 std::swap(MutableCoefficient(last_entry), MutableCoefficient(i));
766 template <
typename IndexType,
typename IteratorType>
769 for (
const EntryIndex i : AllEntryIndices()) {
770 MutableCoefficient(i) *= factor;
774 template <
typename IndexType,
typename IteratorType>
777 for (
const EntryIndex i : AllEntryIndices()) {
778 MutableCoefficient(i) *= factors[GetIndex(i)];
782 template <
typename IndexType,
typename IteratorType>
785 for (
const EntryIndex i : AllEntryIndices()) {
786 MutableCoefficient(i) /= factor;
790 template <
typename IndexType,
typename IteratorType>
793 for (
const EntryIndex i : AllEntryIndices()) {
794 MutableCoefficient(i) /= factors[GetIndex(i)];
798 template <
typename IndexType,
typename IteratorType>
803 for (
const EntryIndex i : AllEntryIndices()) {
808 template <
typename IndexType,
typename IteratorType>
814 for (
const EntryIndex i : AllEntryIndices()) {
819 template <
typename IndexType,
typename IteratorType>
823 if (multiplier == 0.0)
return;
824 for (
const EntryIndex i : AllEntryIndices()) {
829 template <
typename IndexType,
typename IteratorType>
834 AddMultipleToSparseVectorInternal(
true, multiplier, removed_common_index,
835 drop_tolerance, accumulator_vector);
838 template <
typename IndexType,
typename IteratorType>
843 AddMultipleToSparseVectorInternal(
false, multiplier, removed_common_index,
844 drop_tolerance, accumulator_vector);
847 template <
typename IndexType,
typename IteratorType>
854 DCHECK(CheckNoDuplicates());
856 DCHECK_NE(0.0, LookUpCoefficient(common_index));
870 const EntryIndex size_a =
a.num_entries();
871 const EntryIndex size_b =
b.num_entries();
872 const int size_adjustment = delete_common_index ? -2 : 0;
873 const EntryIndex new_size_upper_bound = size_a + size_b + size_adjustment;
874 c.
Reserve(new_size_upper_bound);
876 while ((ia < size_a) && (ib < size_b)) {
877 const Index index_a =
a.GetIndex(ia);
878 const Index index_b =
b.GetIndex(ib);
881 if (index_a == index_b) {
882 if (index_a != common_index) {
883 const Fractional a_coeff_mul = multiplier *
a.GetCoefficient(ia);
889 if (std::abs(sum) > drop_tolerance) {
894 }
else if (!delete_common_index) {
901 }
else if (index_a < index_b) {
913 while (ia < size_a) {
919 while (ib < size_b) {
927 c.
Swap(accumulator_vector);
930 template <
typename IndexType,
typename IteratorType>
933 for (
const EntryIndex i : AllEntryIndices()) {
934 MutableIndex(i) = index_perm[GetIndex(i)];
938 template <
typename IndexType,
typename IteratorType>
941 EntryIndex new_index(0);
942 for (
const EntryIndex i : AllEntryIndices()) {
944 if (index_perm[
index] >= 0) {
945 MutableIndex(new_index) = index_perm[
index];
950 ResizeDown(new_index);
953 template <
typename IndexType,
typename IteratorType>
958 const EntryIndex end(num_entries_);
961 if (i >= end)
return;
962 if (index_perm[GetIndex(i)] >= 0)
break;
966 for (EntryIndex j(i + 1); j < end; ++j) {
967 if (index_perm[GetIndex(j)] < 0) {
968 MutableIndex(i) = GetIndex(j);
983 template <
typename IndexType,
typename IteratorType>
987 for (
const EntryIndex i : AllEntryIndices()) {
988 if (GetIndex(i) ==
index) {
999 template <
typename IndexType,
typename IteratorType>
1004 for (
const EntryIndex i : AllEntryIndices()) {
1005 if (GetIndex(i) != other.
GetIndex(i))
return false;
1011 template <
typename IndexType,
typename IteratorType>
1014 for (
const EntryIndex i : AllEntryIndices()) {
1015 if (i != 0) s +=
", ";
1016 absl::StrAppendFormat(&s,
"[%d]=%g", GetIndex(i).
value(),
1025 #endif // OR_TOOLS_LP_DATA_SPARSE_VECTOR_H_ void Reserve(EntryIndex new_capacity)
void AddEntry(Index index, Fractional value)
void AddMultipleToSparseVectorAndIgnoreCommonIndex(Fractional multiplier, Index removed_common_index, Fractional drop_tolerance, SparseVector *accumulator_vector) const
Fractional LookUpCoefficient(Index index) const
IntegerValue GetCoefficient(const IntegerVariable var, const LinearExpression &expr)
void MoveEntryToFirstPosition(Index index)
Fractional & MutableCoefficient(EntryIndex i)
void ResizeDown(EntryIndex new_size)
void AddMultipleToSparseVectorAndDeleteCommonIndex(Fractional multiplier, Index removed_common_index, Fractional drop_tolerance, SparseVector *accumulator_vector) const
void ApplyPartialIndexPermutation(const IndexPermutation &index_perm)
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
void MoveEntryToLastPosition(Index index)
#define RETURN_VALUE_IF_NULL(x, v)
void DivideByConstant(Fractional factor)
void RemoveNearZeroEntriesWithWeights(Fractional threshold, const DenseVector &weights)
void MultiplyByConstant(Fractional factor)
bool may_contain_duplicates_
void PopulateFromSparseVector(const SparseVector &sparse_vector)
std::unique_ptr< char[]> buffer_
SparseVectorEntry(const Index *indices, const Fractional *coefficients, EntryIndex i)
Permutation< Index > IndexPermutation
void ComponentWiseDivide(const DenseVector &factors)
StrictITIVector< Index, Fractional > DenseVector
void RemoveNearZeroEntries(Fractional threshold, DenseRow *row)
EntryIndex num_entries() const
bool IsEqualTo(const SparseVector &other) const
void PermutedCopyToDenseVector(const IndexPermutation &index_perm, Index num_indices, DenseVector *dense_vector) const
void MoveTaggedEntriesTo(const IndexPermutation &index_perm, SparseVector *output)
typename Iterator::Entry Entry
Fractional coefficient() const
void CopyToDenseVector(Index num_indices, DenseVector *dense_vector) const
#define DCHECK_NE(val1, val2)
void ComponentWiseMultiply(const DenseVector &factors)
Fractional GetFirstCoefficient() const
void SetCoefficient(Index index, Fractional value)
void AppendEntriesWithOffset(const SparseVector &sparse_vector, Index offset)
void AssignToZero(IntType size)
bool CheckNoDuplicates() const
const Fractional * coefficient_
Index & MutableIndex(EntryIndex i)
SparseVector & operator=(const SparseVector &other)
#define DCHECK_GE(val1, val2)
void resize(IntType size)
void RemoveNearZeroEntries(Fractional threshold)
Index GetLastIndex() const
#define DCHECK(condition)
Fractional GetCoefficient(EntryIndex i) const
Fractional * coefficient_
#define RETURN_IF_NULL(x)
Index GetFirstIndex() const
void ApplyIndexPermutation(const IndexPermutation &index_perm)
#define DCHECK_LE(val1, val2)
void Swap(SparseVector *other)
Collection of objects used to extend the Constraint Solver library.
absl::Span< const double > coefficients
void DeleteEntry(Index index)
void PopulateFromDenseVector(const DenseVector &dense_vector)
std::string DebugString() const
Index GetIndex(EntryIndex i) const
Fractional GetLastCoefficient() const
::util::IntegerRange< EntryIndex > AllEntryIndices() const
#define DCHECK_LT(val1, val2)
void AddMultipleToDenseVector(Fractional multiplier, DenseVector *dense_vector) const