Google OR-Tools v9.14
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
elemental.h
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#ifndef OR_TOOLS_MATH_OPT_ELEMENTAL_ELEMENTAL_H_
15#define OR_TOOLS_MATH_OPT_ELEMENTAL_ELEMENTAL_H_
16
17#include <array>
18#include <cstdint>
19#include <memory>
20#include <optional>
21#include <ostream>
22#include <string>
23#include <vector>
24
25#include "absl/log/check.h"
26#include "absl/log/die_if_null.h"
27#include "absl/status/status.h"
28#include "absl/status/statusor.h"
29#include "absl/strings/string_view.h"
39#include "ortools/math_opt/model.pb.h"
40#include "ortools/math_opt/model_update.pb.h"
41
43
44// A MathOpt optimization model and modification trackers.
45//
46// Holds the elements, the attribute values, and tracks modifications to the
47// model by `Diff` objects, and keeps them all in sync. See README.md for
48// details.
49class Elemental {
50 public:
51 // An opaque value type for a reference to an underlying `Diff` (change
52 // tracker).
53 class DiffHandle {
54 public:
55 int64_t id() const { return diff_id_; }
56
57 private:
58 explicit DiffHandle(int64_t diff_id, ThreadSafeIdMap<Diff>* diffs)
59 : diff_id_(diff_id), diffs_(*ABSL_DIE_IF_NULL(diffs)) {}
60
61 int64_t diff_id_;
63
64 friend class Elemental;
65 friend class ElementalTestPeer;
66 };
67
68 explicit Elemental(std::string model_name = "",
69 std::string primary_objective_name = "");
70
71 // The name of this optimization model.
72 const std::string& model_name() const { return model_name_; }
73
74 // The name of the primary objective of this optimization model.
75 const std::string& primary_objective_name() const {
76 return primary_objective_name_;
77 }
78
80 // Elements
82
83 // Creates and returns the id of a new element for the element type `e`.
84 template <ElementType e>
85 ElementId<e> AddElement(const absl::string_view name) {
86 return ElementId<e>(AddElementUntyped(e, name));
87 }
88
89 // Type-erased version of `AddElement`. Prefer the latter.
90 int64_t AddElementUntyped(const ElementType e, const absl::string_view name) {
91 return mutable_element_storage(e).Add(name);
92 }
93
94 // Deletes the element with `id` for element type `e`, returning true on
95 // success and false if no element was deleted (it was already deleted or the
96 // id was not from any existing element).
97 template <ElementType e>
98 bool DeleteElement(const ElementId<e> id) {
99 return DeleteElementUntyped(e, id.value());
101
102 // Type-erased version of `DeleteElement`. Prefer the latter.
103 bool DeleteElementUntyped(ElementType e, int64_t id);
104
105 // Returns true the element with `id` for element type `e` exists (it was
106 // created and not yet deleted).
107 template <ElementType e>
108 bool ElementExists(const ElementId<e> id) const {
109 return ElementExistsUntyped(e, id.value());
111
112 // Type-erased version of `ElementExists`. Prefer the latter.
113 bool ElementExistsUntyped(const ElementType e, const int64_t id) const {
114 return element_storage(e).Exists(id);
116
117 // Returns the name of the element with `id` for element type `e`, or an error
118 // if this element does not exist.
119 template <ElementType e>
120 absl::StatusOr<absl::string_view> GetElementName(
121 const ElementId<e> id) const {
122 return GetElementNameUntyped(e, id.value());
123 }
124
125 // Type-erased version of `GetElementName`. Prefer the latter.
126 absl::StatusOr<absl::string_view> GetElementNameUntyped(
127 const ElementType e, const int64_t id) const {
128 return element_storage(e).GetName(id);
129 }
130
131 // Returns the ids of all elements of element type `e` in the model in an
132 // unsorted, non-deterministic order.
133 template <ElementType e>
137
138 // Type-erased version of `AllElements`. Prefer the latter.
139 std::vector<int64_t> AllElementsUntyped(const ElementType e) const {
140 return element_storage(e).AllIds();
142
143 // Returns the id of next element created for element type `e`.
144 //
145 // Equal to one plus the number of elements that were created for element type
146 // `e`. When no elements have been deleted, this equals num_elements(e).
147 int64_t NextElementId(const ElementType e) const {
148 return element_storage(e).next_id();
150
151 // Returns the number of elements in the model for element type `e`.
152 //
153 // Equal to the number of elements that were created minus the number
154 // deleted for element type `e`.
155 int64_t NumElements(const ElementType e) const {
156 return element_storage(e).size();
158
159 // Increases next_element_id(e) to `id` if it is currently less than `id`.
160 //
161 // Useful for reading a model back from proto, most users should not need to
162 // call this directly.
163 template <ElementType e>
167
168 // Type-erased version of `EnsureNextElementIdAtLeast`. Prefer the latter.
169 void EnsureNextElementIdAtLeastUntyped(const ElementType e, int64_t id) {
170 mutable_element_storage(e).EnsureNextIdAtLeast(id);
172
174 // Attributes
176 struct AlwaysOk {};
177
178 // In all the following functions, `key` must be a valid key for attribute `a`
179 // (i.e. elements must exists for all elements ids of `key`). When this is not
180 // the case, the behavior is defined by one of the following policies:
181 // - Checks whether each element of the key exists, and dies if not.
182 struct DiePolicy {
183 using CheckResultT = AlwaysOk;
184 template <typename T>
185 using Wrapped = T;
186 };
187 // - Checks whether each element of the key exists, and sets `*status` if
188 // not. When `*status` is not OK, the model is not modified and is still
189 // valid.
190 struct StatusPolicy {
191 using CheckResultT = absl::Status;
192 template <typename T>
193 using Wrapped = absl::StatusOr<T>;
194 };
195 // - Does not check whether key elements exists. UB if the key does not exist
196 // (DCHECK-fails in debug mode). Use if you know that the key exists and
197 // you care about performance.
198 struct UBPolicy {
199 using CheckResultT = AlwaysOk;
200 template <typename T>
201 using Wrapped = T;
202 };
204 // Restores the attribute `a` to its default value for all AttrKeys (or for
205 // an Attr0, its only value).
206 template <typename AttrType>
207 void AttrClear(AttrType a);
208
209 // Return the vector of attribute keys where a is non-default.
210 template <typename AttrType>
211 std::vector<AttrKeyFor<AttrType>> AttrNonDefaults(const AttrType a) const {
212 return attrs_[a].NonDefaults();
213 }
214
215 // Returns the number of keys where `a` is non-default.
216 template <typename AttrType>
217 int64_t AttrNumNonDefaults(const AttrType a) const {
218 return attrs_[a].num_non_defaults();
219 }
220
221 // Returns the value of the attr `a` for `key`:
222 // - `get_attr(DoubleAttr1::kVarUb, AttrKey(x))` returns a `double` value if
223 // element id `x` exists, and crashes otherwise. The returned value is
224 // the default value if the attribute has not been set for `x`.
225 // - `get_attr<StatusPolicy>(DoubleAttr1::kVarUb, AttrKey(x))` returns a
226 // valid `StatusOr<double>` if element id `x` exists, and an error
227 // otherwise.
228 template <typename Policy = DiePolicy, typename AttrType>
229 typename Policy::template Wrapped<ValueTypeFor<AttrType>> GetAttr(
230 AttrType a, AttrKeyFor<AttrType> key) const;
231
232 // Returns true if the attr `a` for `key` has a value different from its
233 // default.
234 template <typename Policy = DiePolicy, typename AttrType>
235 typename Policy::template Wrapped<bool> AttrIsNonDefault(
236 AttrType a, AttrKeyFor<AttrType> key) const;
237
238 // Sets the value of the attr `a` for the element `key` to `value`, and
239 // returns true if the value of the attribute has changed.
240 template <typename Policy = DiePolicy, typename AttrType>
241 typename Policy::CheckResultT SetAttr(AttrType a, AttrKeyFor<AttrType> key,
243
244 // Returns the set of all keys `k` such that `k[i] == key_elem` and `k` has a
245 // non-default value for the attribute `a`.
246 template <int i, typename Policy = DiePolicy, typename AttrType = void>
247 typename Policy::template Wrapped<std::vector<AttrKeyFor<AttrType>>> Slice(
248 AttrType a, int64_t key_elem) const;
249
250 // Returns the size of the given slice: This is equivalent to `Slice(a,
251 // key_elem).size()`, but `O(1)`.
252 template <int i, typename Policy = DiePolicy, typename AttrType = void>
253 typename Policy::template Wrapped<int64_t> GetSliceSize(
254 AttrType a, int64_t key_elem) const;
255
256 // Returns a copy of this, but with no diffs. The name of the model can
257 // optionally be replaced by `new_model_name`.
259 std::optional<absl::string_view> new_model_name = std::nullopt) const;
260
262 // Working with proto
264
265 // Returns an equivalent protocol buffer. Fails if the model is too big
266 // to fit in the in-memory representation of the proto (it has more than
267 // 2**31-1 elements of a type or non-defaults for an attribute).
268 absl::StatusOr<ModelProto> ExportModel(bool remove_names = false) const;
269
270 // Creates an equivalent Elemental to `proto`.
271 static absl::StatusOr<Elemental> FromModelProto(const ModelProto& proto);
272
273 // Applies the changes to the model in `update_proto`.
274 absl::Status ApplyUpdateProto(const ModelUpdateProto& update_proto);
275
277 // Diffs
279
280 // Returns the DiffHandle for `id`, if one exists, or nullopt otherwise.
281 std::optional<DiffHandle> GetDiffHandle(int64_t id) const;
282
283 // Returned handle is valid until passed `DeleteDiff` or `*this` is
284 // destructed.
286
287 // Deletes `diff` & invalidates it. Returns false if the handle was invalid or
288 // from the wrong elemental). On success, invalidates `diff`.
289 bool DeleteDiff(DiffHandle diff);
290
291 // The number of diffs currently tracking this.
292 int64_t NumDiffs() const { return diffs_->Size(); }
293
294 // Returns true on success (fails if diff was null, deleted or from the wrong
295 // elemental). Warning: diff is modified (owned by this).
296 bool Advance(DiffHandle diff);
297
298 // Internal use only (users of Elemental cannot access Diff directly), but
299 // prefer to invoking Diff::modified_keys() directly..
300 //
301 // Returns the modified keys in a Diff for an attribute, filtering out the
302 // keys referring to an element that has been deleted.
303 //
304 // This is needed because in some situations where a variable is deleted
305 // we cannot clean up the diff, see README.md.
306 template <typename AttrType>
307 std::vector<AttrKeyFor<AttrType>> ModifiedKeysThatExist(
308 AttrType attr, const Diff& diff) const;
309
310 // Returns a proto describing all changes to the model for `diff` since the
311 // most recent call to `Advance(diff)` (or the creation of `diff` if
312 // `Advance()` was never called).
313 //
314 // Returns std::nullopt the resulting ModelUpdateProto would be the empty
315 // message (there have been no changes to the model to report).
316 //
317 // Fails if the update is too big to fit in the in-memory representation of
318 // the proto (it has more than 2**31-1 elements in a RepeatedField).
319 absl::StatusOr<std::optional<ModelUpdateProto>> ExportModelUpdate(
320 DiffHandle diff, bool remove_names = false) const;
321
322 // Prints out the model by element and attribute. If print_diffs is true, also
323 // prints out the deleted elements and modified keys for each attribute for
324 // each DiffHandle tracked.
325 //
326 // This is a debug format. Do not assume the output is consistent across CLs
327 // and do not parse this format.
328 std::string DebugString(bool print_diffs = true) const;
329
330 private:
331 DiePolicy::CheckResultT CheckElementExists(ElementType elem_type,
332 int64_t elem_id, DiePolicy) const;
333 StatusPolicy::CheckResultT CheckElementExists(ElementType elem_type,
334 int64_t elem_id,
335 StatusPolicy) const;
336 UBPolicy::CheckResultT CheckElementExists(ElementType elem_type,
337 int64_t elem_id, UBPolicy) const;
338
339 template <typename AttrType>
340 bool AttrKeyExists(AttrType attr, AttrKeyFor<AttrType> key) const;
341
342 template <typename Policy, typename AttrType>
343 typename Policy::CheckResultT CheckAttrKeyExists(
344 AttrType a, AttrKeyFor<AttrType> key) const;
345
346 template <typename AttrType, int i>
347 void UpdateAttrOnElementDeleted(AttrType a, int64_t id);
348
349 std::array<int64_t, kNumElements> CurrentCheckpoint() const;
350
351 const ElementStorage& element_storage(const ElementType e) const {
352 // TODO(b/365997645): post C++ 23, prefer std::to_underlying(e).
353 return elements_[static_cast<int>(e)];
354 }
355
356 ElementStorage& mutable_element_storage(const ElementType e) {
357 return elements_[static_cast<int>(e)];
358 }
359
360 std::string model_name_;
361 std::string primary_objective_name_;
362 std::array<ElementStorage, kNumElements> elements_;
363 template <int i>
364 using StorageForAttrType =
365 AttrStorage<typename AllAttrs::TypeDescriptor<i>::ValueType,
366 AllAttrs::TypeDescriptor<i>::kNumKeyElements,
367 typename AllAttrs::TypeDescriptor<i>::Symmetry>;
368 AttrMap<StorageForAttrType> attrs_;
369 // For each attribute whose value is an element, we need to keep a map of
370 // element to the set of keys whose value refers to that element. This
371 // is used to erase the attribute when the element is deleted.
372 // This is kept outside of `attrs_` so that we can update the diffs when
373 // element deletions trigger attribute deletions.
374 template <int i>
375 using ElementRefTrackerForAttrType =
377 AttrMap<ElementRefTrackerForAttrType> element_ref_trackers_;
378 // Note: it is important that this is a unique_ptr for two reasons:
379 // 1. We need a stable memory address for diffs_ to refer to in DiffHandle,
380 // and the Elemental type is moveable.
381 // 2. We want Elemental to be moveable, but ThreadSafeIdMap<Diff> is not.
382 std::unique_ptr<ThreadSafeIdMap<Diff>> diffs_ =
383 std::make_unique<ThreadSafeIdMap<Diff>>();
384};
385
386template <typename Sink>
387void AbslStringify(Sink& sink, const Elemental& elemental) {
388 sink.Append(elemental.DebugString());
389}
390
391std::ostream& operator<<(std::ostream& ostr, const Elemental& elemental);
392
393
394// Inline and template implementation
396template <typename AttrType>
397void Elemental::AttrClear(const AttrType a) {
398 // Note: this is slightly faster than setting each non-default back to the
399 // default value.
400 const std::vector<AttrKeyFor<AttrType>> non_defaults = AttrNonDefaults(a);
401 if (!non_defaults.empty()) {
402 for (auto& [unused, diff] : diffs_->UpdateAndGetAll()) {
403 for (const auto key : non_defaults) {
404 diff->SetModified(a, key);
405 }
407 }
408 attrs_[a].Clear();
410 element_ref_trackers_[a].Clear();
411 }
412}
413
414#define ELEMENTAL_RETURN_IF_ERROR(expr) \
415 { \
416 auto error = (expr); \
417 if constexpr (!std::is_same_v<decltype(error), AlwaysOk>) { \
418 if (!error.ok()) { \
419 return error; \
420 } \
421 } \
422 }
424template <typename Policy, typename AttrType>
425typename Policy::template Wrapped<ValueTypeFor<AttrType>> Elemental::GetAttr(
426 const AttrType a, const AttrKeyFor<AttrType> key) const {
427 ELEMENTAL_RETURN_IF_ERROR(CheckAttrKeyExists<Policy>(a, key));
428 return attrs_[a].Get(key);
429}
430
431template <typename Policy, typename AttrType>
432typename Policy::template Wrapped<bool> Elemental::AttrIsNonDefault(
433 const AttrType a, const AttrKeyFor<AttrType> key) const {
434 ELEMENTAL_RETURN_IF_ERROR(CheckAttrKeyExists<Policy>(a, key));
435 return attrs_[a].IsNonDefault(key);
436}
437
438template <typename Policy, typename AttrType>
439typename Policy::CheckResultT Elemental::SetAttr(
440 const AttrType a, const AttrKeyFor<AttrType> key,
442 ELEMENTAL_RETURN_IF_ERROR(CheckAttrKeyExists<Policy>(a, key));
443 const std::optional<ValueTypeFor<AttrType>> prev_value =
444 attrs_[a].Set(key, value);
445 if (prev_value.has_value()) {
447 element_ref_trackers_[a].Untrack(key, *prev_value);
449 for (auto& [unused, diff] : diffs_->UpdateAndGetAll()) {
450 diff->SetModified(a, key);
451 }
453 element_ref_trackers_[a].Track(key, value);
454 }
455 }
456 return {};
457}
458
459template <int i, typename Policy, typename AttrType>
460typename Policy::template Wrapped<std::vector<AttrKeyFor<AttrType>>>
461Elemental::Slice(const AttrType a, const int64_t key_elem) const {
463 CheckElementExists(GetElementTypes<AttrType>(a)[i], key_elem, Policy{}));
464 return attrs_[a].template Slice<i>(key_elem);
465}
466
467template <int i, typename Policy, typename AttrType>
468typename Policy::template Wrapped<int64_t> Elemental::GetSliceSize(
469 const AttrType a, const int64_t key_elem) const {
471 CheckElementExists(GetElementTypes<AttrType>(a)[i], key_elem, Policy{}));
472 return attrs_[a].template GetSliceSize<i>(key_elem);
473}
474
475inline Elemental::DiePolicy::CheckResultT Elemental::CheckElementExists(
476 const ElementType elem_type, const int64_t elem_id, DiePolicy) const {
477 // This is ~30% faster than:
478 // CHECK_OK(CheckElementExistsUntyped(elem_type, elem_id, StatusPolicy{}));
479 CHECK(ElementExistsUntyped(elem_type, elem_id))
480 << "no element with id " << elem_id << " for element type " << elem_type;
481 return {};
482}
483
484inline Elemental::StatusPolicy::CheckResultT Elemental::CheckElementExists(
485 const ElementType elem_type, const int64_t elem_id, StatusPolicy) const {
486 if (!ElementExistsUntyped(elem_type, elem_id)) {
488 << "no element with id " << elem_id << " for element type "
489 << elem_type;
490 }
491 return absl::OkStatus();
492}
493
494inline Elemental::UBPolicy::CheckResultT Elemental::CheckElementExists(
495 const ElementType elem_type, const int64_t elem_id, UBPolicy) const {
496 // Try to be useful in debug mode.
497 DCHECK_OK(CheckElementExists(elem_type, elem_id, StatusPolicy{}));
498 return {};
499}
500
501template <typename AttrType>
502bool Elemental::AttrKeyExists(const AttrType attr,
503 const AttrKeyFor<AttrType> key) const {
504 for (int i = 0; i < key.size(); ++i) {
505 if (!ElementExistsUntyped(GetElementTypes<AttrType>(attr)[i], key[i])) {
506 return false;
507 }
508 }
509 return true;
510}
511
512template <typename Policy, typename AttrType>
513typename Policy::CheckResultT Elemental::CheckAttrKeyExists(
514 const AttrType a, const AttrKeyFor<AttrType> key) const {
515 for (int i = 0; i < key.size(); ++i) {
517 CheckElementExists(GetElementTypes<AttrType>(a)[i], key[i], Policy{}));
518 }
519 return {};
520}
521
522template <typename AttrType>
523std::vector<AttrKeyFor<AttrType>> Elemental::ModifiedKeysThatExist(
524 AttrType attr, const Diff& diff) const {
525 using Key = AttrKeyFor<AttrType>;
526 std::vector<Key> keys;
527 // Can be a slight overestimate.
528 keys.reserve(diff.modified_keys(attr).size());
529 for (const Key key : diff.modified_keys(attr)) {
530 if constexpr (Key::size() > 1) {
531 if (AttrKeyExists(attr, key)) {
532 keys.push_back(key);
533 }
534 } else {
535 keys.push_back(key);
536 }
537 }
538 return keys;
539}
540
541#undef ELEMENTAL_RETURN_IF_ERROR
542
543} // namespace operations_research::math_opt
544
545#endif // OR_TOOLS_MATH_OPT_ELEMENTAL_ELEMENTAL_H_
A strongly typed element id. Value type.
Definition elements.h:64
int64_t size() const
Returns the number of elements added and not erased.
int64_t Add(const absl::string_view name)
Creates a new element and returns its id.
bool Exists(const int64_t id) const
Returns true an element with this id was created and not yet erased.
int64_t NumDiffs() const
The number of diffs currently tracking this.
Definition elemental.h:300
absl::StatusOr< absl::string_view > GetElementNameUntyped(const ElementType e, const int64_t id) const
Type-erased version of GetElementName. Prefer the latter.
Definition elemental.h:128
Policy::template Wrapped< int64_t > GetSliceSize(AttrType a, int64_t key_elem) const
Definition elemental.h:477
Elemental(std::string model_name="", std::string primary_objective_name="")
Definition elemental.cc:38
Policy::CheckResultT SetAttr(AttrType a, AttrKeyFor< AttrType > key, ValueTypeFor< AttrType > value)
Definition elemental.h:448
std::optional< DiffHandle > GetDiffHandle(int64_t id) const
Returns the DiffHandle for id, if one exists, or nullopt otherwise.
Definition elemental.cc:52
bool ElementExists(const ElementId< e > id) const
Definition elemental.h:110
std::vector< AttrKeyFor< AttrType > > AttrNonDefaults(const AttrType a) const
Return the vector of attribute keys where a is non-default.
Definition elemental.h:215
int64_t AttrNumNonDefaults(const AttrType a) const
Returns the number of keys where a is non-default.
Definition elemental.h:221
const std::string & primary_objective_name() const
The name of the primary objective of this optimization model.
Definition elemental.h:75
absl::StatusOr< ModelProto > ExportModel(bool remove_names=false) const
std::vector< int64_t > AllElementsUntyped(const ElementType e) const
Type-erased version of AllElements. Prefer the latter.
Definition elemental.h:141
std::string DebugString(bool print_diffs=true) const
absl::StatusOr< absl::string_view > GetElementName(const ElementId< e > id) const
Definition elemental.h:122
void EnsureNextElementIdAtLeastUntyped(const ElementType e, int64_t id)
Type-erased version of EnsureNextElementIdAtLeast. Prefer the latter.
Definition elemental.h:171
bool DeleteElement(const ElementId< e > id)
Definition elemental.h:100
const std::string & model_name() const
The name of this optimization model.
Definition elemental.h:72
Policy::template Wrapped< bool > AttrIsNonDefault(AttrType a, AttrKeyFor< AttrType > key) const
Definition elemental.h:441
absl::Status ApplyUpdateProto(const ModelUpdateProto &update_proto)
Applies the changes to the model in update_proto.
bool DeleteElementUntyped(ElementType e, int64_t id)
Type-erased version of DeleteElement. Prefer the latter.
Definition elemental.cc:86
void AttrClear(AttrType a)
Inline and template implementation.
Definition elemental.h:406
Policy::template Wrapped< ValueTypeFor< AttrType > > GetAttr(AttrType a, AttrKeyFor< AttrType > key) const
Definition elemental.h:434
ElementIdsVector< e > AllElements() const
Definition elemental.h:136
Policy::template Wrapped< std::vector< AttrKeyFor< AttrType > > > Slice(AttrType a, int64_t key_elem) const
Definition elemental.h:470
void EnsureNextElementIdAtLeast(const ElementId< e > id)
Definition elemental.h:166
std::vector< AttrKeyFor< AttrType > > ModifiedKeysThatExist(AttrType attr, const Diff &diff) const
Definition elemental.h:532
absl::StatusOr< std::optional< ModelUpdateProto > > ExportModelUpdate(DiffHandle diff, bool remove_names=false) const
Elemental Clone(std::optional< absl::string_view > new_model_name=std::nullopt) const
Definition elemental.cc:155
ElementId< e > AddElement(const absl::string_view name)
Creates and returns the id of a new element for the element type e.
Definition elemental.h:87
int64_t NextElementId(const ElementType e) const
Definition elemental.h:149
bool ElementExistsUntyped(const ElementType e, const int64_t id) const
Type-erased version of ElementExists. Prefer the latter.
Definition elemental.h:115
int64_t AddElementUntyped(const ElementType e, const absl::string_view name)
Type-erased version of AddElement. Prefer the latter.
Definition elemental.h:92
static absl::StatusOr< Elemental > FromModelProto(const ModelProto &proto)
Creates an equivalent Elemental to proto.
int64_t NumElements(const ElementType e) const
Definition elemental.h:157
#define ELEMENTAL_RETURN_IF_ERROR(expr)
Definition elemental.h:423
An object oriented wrapper for quadratic constraints in ModelStorage.
Definition gurobi_isv.cc:28
AttrKey< AttrTypeDescriptorT< AttrType >::kNumKeyElements, typename AttrTypeDescriptorT< AttrType >::Symmetry > AttrKeyFor
The type of the AttrKey for attribute type AttrType.
static constexpr bool is_element_id_v
Definition elements.h:262
void AbslStringify(Sink &sink, const AttrT attr_type)
Definition attributes.h:336
std::ostream & operator<<(std::ostream &ostr, const SecondOrderConeConstraint &constraint)
constexpr std::array< ElementType, GetAttrKeySize< attr >()> GetElementTypes()
ElementRefTracker< typename Descriptor::ValueType, Descriptor::kNumKeyElements, typename Descriptor::Symmetry > ElementRefTrackerForAttrTypeDescriptor
The ElementRefTracker for a given attribute type descriptor.
typename AttrTypeDescriptorT< AttrType >::ValueType ValueTypeFor
The value type for attribute type AttrType.
constexpr std::array< ElementType, GetAttrKeySize< AttrType >()> GetElementTypes(const AttrType attr)
StatusBuilder InvalidArgumentErrorBuilder()