14#ifndef OR_TOOLS_MATH_OPT_ELEMENTAL_ELEMENTAL_H_
15#define OR_TOOLS_MATH_OPT_ELEMENTAL_ELEMENTAL_H_
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"
55 int64_t
id()
const {
return diff_id_; }
59 : diff_id_(diff_id), diffs_(*ABSL_DIE_IF_NULL(diffs)) {}
72 const std::string&
model_name()
const {
return model_name_; }
76 return primary_objective_name_;
84 template <ElementType e>
91 return mutable_element_storage(e).
Add(name);
97 template <ElementType e>
107 template <ElementType e>
114 return element_storage(e).
Exists(
id);
119 template <ElementType e>
128 return element_storage(e).GetName(
id);
133 template <ElementType e>
140 return element_storage(e).
AllIds();
148 return element_storage(e).
next_id();
156 return element_storage(e).
size();
163 template <ElementType e>
184 template <
typename T>
192 template <
typename T>
193 using Wrapped = absl::StatusOr<T>;
200 template <
typename T>
206 template <
typename AttrType>
210 template <
typename AttrType>
211 std::vector<AttrKeyFor<AttrType>>
AttrNonDefaults(
const AttrType a)
const {
212 return attrs_[a].NonDefaults();
216 template <
typename AttrType>
218 return attrs_[a].num_non_defaults();
228 template <
typename Policy = DiePolicy,
typename AttrType>
229 typename Policy::template Wrapped<ValueTypeFor<AttrType>>
GetAttr(
234 template <
typename Policy = DiePolicy,
typename AttrType>
240 template <
typename Policy = DiePolicy,
typename AttrType>
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;
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;
259 std::optional<absl::string_view> new_model_name = std::nullopt)
const;
268 absl::StatusOr<ModelProto>
ExportModel(
bool remove_names =
false)
const;
271 static absl::StatusOr<Elemental>
FromModelProto(
const ModelProto& proto);
292 int64_t
NumDiffs()
const {
return diffs_->Size(); }
306 template <
typename AttrType>
308 AttrType attr,
const Diff& diff)
const;
320 DiffHandle diff,
bool remove_names =
false)
const;
328 std::string
DebugString(
bool print_diffs =
true)
const;
339 template <
typename AttrType>
342 template <
typename Policy,
typename AttrType>
343 typename Policy::CheckResultT CheckAttrKeyExists(
346 template <
typename AttrType,
int i>
347 void UpdateAttrOnElementDeleted(AttrType a, int64_t
id);
349 std::array<int64_t, kNumElements> CurrentCheckpoint()
const;
353 return elements_[
static_cast<int>(e)];
357 return elements_[
static_cast<int>(e)];
360 std::string model_name_;
361 std::string primary_objective_name_;
362 std::array<ElementStorage, kNumElements> elements_;
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_;
375 using ElementRefTrackerForAttrType =
377 AttrMap<ElementRefTrackerForAttrType> element_ref_trackers_;
382 std::unique_ptr<ThreadSafeIdMap<Diff>> diffs_ =
383 std::make_unique<ThreadSafeIdMap<Diff>>();
386template <
typename Sink>
388 sink.Append(elemental.DebugString());
396template <
typename AttrType>
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);
410 element_ref_trackers_[a].Clear();
414#define ELEMENTAL_RETURN_IF_ERROR(expr) \
416 auto error = (expr); \
417 if constexpr (!std::is_same_v<decltype(error), AlwaysOk>) { \
424template <
typename Policy,
typename AttrType>
428 return attrs_[a].Get(key);
431template <
typename Policy,
typename AttrType>
435 return attrs_[a].IsNonDefault(key);
438template <
typename Policy,
typename AttrType>
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);
453 element_ref_trackers_[a].Track(key, value);
459template <
int i,
typename Policy,
typename AttrType>
460typename Policy::template Wrapped<std::vector<AttrKeyFor<AttrType>>>
464 return attrs_[a].template
Slice<i>(key_elem);
467template <
int i,
typename Policy,
typename AttrType>
469 const AttrType a,
const int64_t key_elem)
const {
476 const ElementType elem_type,
const int64_t elem_id, DiePolicy)
const {
480 <<
"no element with id " << elem_id <<
" for element type " << elem_type;
485 const ElementType elem_type,
const int64_t elem_id, StatusPolicy)
const {
488 <<
"no element with id " << elem_id <<
" for element type "
491 return absl::OkStatus();
495 const ElementType elem_type,
const int64_t elem_id, UBPolicy)
const {
497 DCHECK_OK(CheckElementExists(elem_type, elem_id,
StatusPolicy{}));
501template <
typename AttrType>
502bool Elemental::AttrKeyExists(
const AttrType attr,
504 for (
int i = 0;
i < key.size(); ++
i) {
512template <
typename Policy,
typename AttrType>
513typename Policy::CheckResultT Elemental::CheckAttrKeyExists(
515 for (
int i = 0;
i < key.size(); ++
i) {
522template <
typename AttrType>
524 AttrType attr,
const Diff& diff)
const {
526 std::vector<Key> keys;
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)) {
541#undef ELEMENTAL_RETURN_IF_ERROR
A strongly typed element id. Value type.
int64_t size() const
Returns the number of elements added and not erased.
void EnsureNextIdAtLeast(const int64_t id)
std::vector< int64_t > AllIds() const
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.
friend class ElementalTestPeer
int64_t NumDiffs() const
The number of diffs currently tracking this.
absl::StatusOr< absl::string_view > GetElementNameUntyped(const ElementType e, const int64_t id) const
Type-erased version of GetElementName. Prefer the latter.
Policy::template Wrapped< int64_t > GetSliceSize(AttrType a, int64_t key_elem) const
Elemental(std::string model_name="", std::string primary_objective_name="")
bool Advance(DiffHandle diff)
Policy::CheckResultT SetAttr(AttrType a, AttrKeyFor< AttrType > key, ValueTypeFor< AttrType > value)
std::optional< DiffHandle > GetDiffHandle(int64_t id) const
Returns the DiffHandle for id, if one exists, or nullopt otherwise.
bool ElementExists(const ElementId< e > id) const
std::vector< AttrKeyFor< AttrType > > AttrNonDefaults(const AttrType a) const
Return the vector of attribute keys where a is non-default.
int64_t AttrNumNonDefaults(const AttrType a) const
Returns the number of keys where a is non-default.
const std::string & primary_objective_name() const
The name of the primary objective of this optimization model.
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.
std::string DebugString(bool print_diffs=true) const
absl::StatusOr< absl::string_view > GetElementName(const ElementId< e > id) const
void EnsureNextElementIdAtLeastUntyped(const ElementType e, int64_t id)
Type-erased version of EnsureNextElementIdAtLeast. Prefer the latter.
bool DeleteElement(const ElementId< e > id)
const std::string & model_name() const
The name of this optimization model.
Policy::template Wrapped< bool > AttrIsNonDefault(AttrType a, AttrKeyFor< AttrType > key) const
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.
void AttrClear(AttrType a)
Inline and template implementation.
Policy::template Wrapped< ValueTypeFor< AttrType > > GetAttr(AttrType a, AttrKeyFor< AttrType > key) const
ElementIdsVector< e > AllElements() const
Policy::template Wrapped< std::vector< AttrKeyFor< AttrType > > > Slice(AttrType a, int64_t key_elem) const
void EnsureNextElementIdAtLeast(const ElementId< e > id)
std::vector< AttrKeyFor< AttrType > > ModifiedKeysThatExist(AttrType attr, const Diff &diff) const
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
bool DeleteDiff(DiffHandle diff)
ElementId< e > AddElement(const absl::string_view name)
Creates and returns the id of a new element for the element type e.
int64_t NextElementId(const ElementType e) const
bool ElementExistsUntyped(const ElementType e, const int64_t id) const
Type-erased version of ElementExists. Prefer the latter.
int64_t AddElementUntyped(const ElementType e, const absl::string_view name)
Type-erased version of AddElement. Prefer the latter.
static absl::StatusOr< Elemental > FromModelProto(const ModelProto &proto)
Creates an equivalent Elemental to proto.
int64_t NumElements(const ElementType e) const
#define ELEMENTAL_RETURN_IF_ERROR(expr)
An object oriented wrapper for quadratic constraints in ModelStorage.
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
void AbslStringify(Sink &sink, const AttrT attr_type)
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()
absl::Status CheckResultT
absl::StatusOr< T > Wrapped