14#ifndef OR_TOOLS_MATH_OPT_ELEMENTAL_ATTR_KEY_H_
15#define OR_TOOLS_MATH_OPT_ELEMENTAL_ATTR_KEY_H_
24#include "absl/container/flat_hash_map.h"
25#include "absl/container/flat_hash_set.h"
26#include "absl/log/check.h"
27#include "absl/strings/str_cat.h"
28#include "absl/strings/str_join.h"
29#include "absl/types/span.h"
38template <
int n,
typename Symmetry = NoSymmetry>
47 template <
typename... Ints,
48 typename = std::enable_if_t<(
sizeof...(Ints) == n &&
49 (std::is_integral_v<Ints> && ...))>>
50 explicit constexpr AttrKey(
const Ints... ids) {
51 auto push_back = [
this, i = 0](
auto e)
mutable { element_ids_[i++] = e; };
52 (push_back(ids), ...);
53 Symmetry::Enforce(element_ids_);
57 typename = std::enable_if_t<(
sizeof...(element_types) == n)>>
61 constexpr AttrKey(std::array<value_type, n> ids)
63 Symmetry::Enforce(element_ids_);
68 return AttrKey(key.element_ids_);
72 static absl::StatusOr<AttrKey>
FromRange(absl::Span<const int64_t> range) {
73 if (range.size() != n) {
74 return ::util::InvalidArgumentErrorBuilder()
75 <<
"cannot build AttrKey<" << n <<
"> from a range of size "
79 std::copy(range.begin(), range.end(), result.element_ids_.begin());
80 Symmetry::Enforce(result.element_ids_);
87 static constexpr int size() {
return n; }
93 return element_ids_[dim];
98 return element_ids_[dim];
104 return element_ids_.data() + element_ids_.size();
114 for (
int i = 0; i < n; ++i) {
115 if (l.element_ids_[i] != r.element_ids_[i]) {
124 for (
int i = 0; i < n; ++i) {
125 if (l.element_ids_[i] < r.element_ids_[i]) {
128 if (l.element_ids_[i] > r.element_ids_[i]) {
137 for (
int i = 0; i < n; ++i) {
138 if (l.element_ids_[i] < r.element_ids_[i]) {
141 if (l.element_ids_[i] > r.element_ids_[i]) {
156 template <
typename H>
158 return H::combine_contiguous(std::move(h), a.element_ids_.data(), n);
162 template <
typename Sink>
164 sink.Append(absl::StrCat(
165 "AttrKey(", absl::StrJoin(absl::MakeSpan(key.element_ids_),
", "),
173 static_assert(dim >= 0);
174 static_assert(dim < n);
176 for (
int i = 0; i < dim; ++i) {
177 result.element_ids_[i] = element_ids_[i];
179 for (
int i = dim + 1; i < n; ++i) {
180 result.element_ids_[i - 1] = element_ids_[i];
187 template <
int dim,
typename NewSymmetry>
189 static_assert(dim >= 0);
190 static_assert(dim < n + 1);
192 for (
int i = 0; i < dim; ++i) {
193 result.element_ids_[i] = element_ids_[i];
195 result.element_ids_[dim] = elem;
196 for (
int i = dim + 1; i < n + 1; ++i) {
197 result.element_ids_[i] = element_ids_[i - 1];
199 DCHECK(NewSymmetry::Validate(result.element_ids_))
200 << result <<
" does not have `" << NewSymmetry::GetName()
206 template <
int other_n,
typename OtherSymmetry>
208 std::array<value_type, n> element_ids_;
212template <
typename... Ints>
219template <
int n,
typename Symmetry>
226template <
int n,
typename Symmetry>
228 ostr << absl::StrCat(key);
239template <
typename Symmetry,
typename V>
245 template <
typename ValueT>
251 : value_(other.value_) {}
255 DCHECK_NE(value_,
nullptr);
259 DCHECK_NE(value_,
nullptr);
265 DCHECK_NE(value_,
nullptr);
272 return l.value_ == r.value_;
280 explicit IteratorImpl(ValueT& value) : value_(&value) {}
282 ValueT* value_ =
nullptr;
290 bool empty()
const {
return !engaged_; }
291 size_t size()
const {
return engaged_ ? 1 : 0; }
314 template <
typename... Args>
317 return std::make_pair(
iterator(value_),
false);
321 return std::make_pair(
iterator(value_),
true);
326 return std::make_pair(
iterator(value_),
false);
330 return std::make_pair(
iterator(value_),
true);
336 static_assert(std::is_trivially_destructible_v<value_type>);
338 bool engaged_ =
false;
345template <
typename AttrKeyT,
346 typename = std::enable_if_t<is_attr_key_v<AttrKeyT>>>
348 (AttrKeyT::size() > 0), absl::flat_hash_set<AttrKeyT>,
353template <
typename AttrKeyT,
typename V,
354 typename = std::enable_if_t<is_attr_key_v<AttrKeyT>>>
356 std::conditional_t<(AttrKeyT::size() > 0), absl::flat_hash_map<AttrKeyT, V>,
358 std::pair<AttrKeyT, V>>>;
friend void AbslStringify(Sink &sink, const AttrKey &key)
AttrKey is printable for logging and tests.
AttrKey< n - 1, NoSymmetry > RemoveElement() const
constexpr AttrKey(const Ints... ids)
constexpr const value_type * begin() const
Element iteration.
constexpr const value_type * end() const
friend constexpr bool operator<=(const AttrKey &l, const AttrKey &r)
friend constexpr bool operator<(const AttrKey &l, const AttrKey &r)
static constexpr AttrKey Canonicalize(AttrKey< n, NoSymmetry > key)
Canonicalizes a non-canonical key, i.e., enforces the symmetries.
static absl::StatusOr< AttrKey > FromRange(absl::Span< const int64_t > range)
Creates a key from a range of n elements.
constexpr AttrKey(const AttrKey &)=default
friend constexpr bool operator==(const AttrKey &l, const AttrKey &r)
constexpr value_type & operator[](const int dim)
constexpr AttrKey(std::array< value_type, n > ids)
constexpr AttrKey()
Default constructor: values are uninitialized.
friend H AbslHashValue(H h, const AttrKey &a)
AttrKey< n+1, NewSymmetry > AddElement(const value_type elem) const
constexpr value_type operator[](const int dim) const
Element access.
constexpr AttrKey(const ElementId< element_types >... ids)
friend constexpr bool operator>(const AttrKey &l, const AttrKey &r)
constexpr AttrKey & operator=(const AttrKey &)=default
friend constexpr bool operator>=(const AttrKey &l, const AttrKey &r)
static constexpr int size()
A strongly typed element id. Value type.
int64_t value() const
Returns the raw id value.
ValueT & operator*() const
Dereference.
friend bool operator!=(const IteratorImpl &l, const IteratorImpl &r)
IteratorImpl(const IteratorImpl< std::remove_cv_t< ValueT > > &other)
iterator converts to const_iterator.
friend bool operator==(const IteratorImpl &l, const IteratorImpl &r)
Equality.
ValueT * operator->() const
IteratorImpl & operator++()
Increment.
friend class AttrKey0RawSet
AttrKey< 0, Symmetry > Key
IteratorImpl< const value_type > const_iterator
const_iterator find(Key) const
std::pair< iterator, bool > try_emplace(Key, Args &&... args)
const_iterator end() const
size_t erase(const_iterator)
const_iterator begin() const
std::pair< iterator, bool > insert(const value_type &v)
IteratorImpl< value_type > iterator
An object oriented wrapper for quadratic constraints in ModelStorage.
AttrKey(Ints... dims) -> AttrKey< sizeof...(Ints), NoSymmetry >
CTAD for AttrKey(1,2).
std::conditional_t<(AttrKeyT::size() > 0), absl::flat_hash_set< AttrKeyT >, detail::AttrKey0RawSet< typename AttrKeyT::SymmetryT, AttrKeyT > > AttrKeyHashSet
A hash set of AttrKeyT, where AttrKeyT is an AttrKey<n, Symmetry>.
std::ostream & operator<<(std::ostream &ostr, const SecondOrderConeConstraint &constraint)
static constexpr bool is_attr_key_v
std::conditional_t<(AttrKeyT::size() > 0), absl::flat_hash_map< AttrKeyT, V >, detail::AttrKey0RawSet< typename AttrKeyT::SymmetryT, std::pair< AttrKeyT, V > > > AttrKeyHashMap
A tag for no symmetry between two elements.
Traits to detect whether T is an AttrKey.