Google OR-Tools v9.14
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
model_storage_item.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_STORAGE_MODEL_STORAGE_ITEM_H_
15#define OR_TOOLS_MATH_OPT_STORAGE_MODEL_STORAGE_ITEM_H_
16
17#include <cstdint>
18#include <ostream>
19#include <type_traits>
20#include <utility>
21
22#include "absl/log/check.h"
23#include "absl/strings/string_view.h"
26
28
29// Represents an item that is stored in the ModelStorage.
30// ModelStorageItem is a value type.
32 public:
33 ModelStorageCPtr storage() const { return storage_; }
34
35 protected:
37
38 // Disallow slicing
39 // (https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-copy-virtual):
44
45 ~ModelStorageItem() = default;
46
47 private:
48 ModelStorageCPtr storage_;
49};
50
51// Whether `ModelStorageElement` should define equality operators.
56
57namespace internal {
58void FormatModelStorageElement(std::ostream& ostr, ElementType element_type,
59 absl::string_view name, int64_t id);
60} // namespace internal
61
62// Typed model storage item. All elemental types (Variables, LinearConstraint,
63// ...) in the model derived from this. Some additional concepts are currently
64// not typed (and derive from `ModelStorageItem` instead):
65// - SOS constraints: we'll migrate them to `ModelStorageElement` once they
66// are implemented in Elemental.
67// - `QuadraticTermKey` is only used transactionally to build the model, it's
68// not stored in the model.
69// - `Objective` is conceptually typed, but exposes a specific, optional-based
70// API to discriminate between the primary and secondaries objectives.
71// `ModelStorageElement` is a value type and implements
72// https://abseil.io/docs/cpp/guides/hash.
73template <ElementType element_type, typename Derived,
74 ModelStorageElementEquality generate_equality =
77 public:
78 // The typed integer used for ids.
80
83
84 // TODO(b/395843100): Remove this, use `typed_id()` or `typed_id().value()`
85 // instead.
86 int64_t id() const { return id_.value(); }
87
88 IdType typed_id() const { return id_; }
89
90 template <typename H>
91 friend H AbslHashValue(H h, const Derived& element) {
92 return H::combine(std::move(h), element.id_.value(), element.storage());
93 }
94
95 template <ModelStorageElementEquality equality = generate_equality>
96 friend std::enable_if_t<
98 operator==(const Derived& lhs, const Derived& rhs) {
99 return lhs.id_ == rhs.id_ && lhs.storage() == rhs.storage();
100 }
101
102 template <ModelStorageElementEquality equality = generate_equality>
103 friend std::enable_if_t<
105 operator!=(const Derived& lhs, const Derived& rhs) {
106 return !(lhs == rhs);
107 }
108
109 // Note: for unnamed elements, we print the element type and id, but we don't
110 // commit to the exect format.
111 friend std::ostream& operator<<(std::ostream& ostr, const Derived& element) {
112 internal::FormatModelStorageElement(ostr, element_type, element.name(),
113 element.typed_id().value());
114 return ostr;
115 }
116
117 protected:
118 // Disallow slicing
119 // (https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-copy-virtual):
124
126
127 private:
128 IdType id_;
129};
130
131// A trait that detects whether a type derives from `ModelStorageElement<e>` for
132// some `e`.
133template <typename T>
135 private:
136 template <ElementType element_type, typename Derived,
138 static constexpr bool IsModelStorageElement(
140 return true;
141 }
142
143 static constexpr bool IsModelStorageElement(...) { return false; }
144
145 public:
146 static constexpr bool value =
147 IsModelStorageElement(static_cast<const T*>(nullptr));
148};
149
150// Represents an item that contains a bunch of items that live in the same model
151// storage. The container is considered to be associated to a given model iff it
152// has at least one item. Derived classes should maintain this invariant.
153// In particular, they should call `SetOrCheckStorage` when an item is added and
154// they should clear the storage when becoming empty (this includes being moved
155// from if that clears the items in the container, see comments on the move
156// constructor).
158 public:
159 // Returns `nullptr` if the container is not associated with any model
160 // (`SetOrCheckStorage` has never been called, or the container was
161 // emptied/moved from).
162 NullableModelStorageCPtr storage() const { return storage_; }
163
164 protected:
166 const NullableModelStorageCPtr storage = nullptr)
167 : storage_(storage) {}
168
169 // Disallow slicing
170 // (https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-copy-virtual):
173 default;
174
175 // When moving we're leaving the moved-from object unassociated with any
176 // model. Derived classes should hold no items after being moved from.
178 : storage_(std::exchange(other.storage_, nullptr)) {}
180 storage_ = std::exchange(other.storage_, nullptr);
181 return *this;
182 }
183
184 // Sets the storage_ to the input value if nullptr, else CHECKs that `item`
185 // is associated with the same storage.
187 SetOrCheckStorageImpl(item.storage());
188 }
189
190 // Same as above, but additionally checks that the input container is already
191 // associated with a storage.
193 CHECK(container.storage() != nullptr) << "appending an empty container";
194 SetOrCheckStorageImpl(container.storage());
195 }
196
197 private:
198 void SetOrCheckStorageImpl(const ModelStorageCPtr storage) {
199 if (storage_ != nullptr) {
200 CHECK_EQ(storage, storage_)
201 << "The input objects belongs to another model.";
202 return;
203 }
204 storage_ = storage;
205 }
206
207 // We start not associated with any model storage.
209};
210
211} // namespace operations_research::math_opt
212
213#endif // OR_TOOLS_MATH_OPT_STORAGE_MODEL_STORAGE_ITEM_H_
A strongly typed element id. Value type.
Definition elements.h:64
friend std::enable_if_t< equality==ModelStorageElementEquality::kWithEquality, bool > operator!=(const Derived &lhs, const Derived &rhs)
ModelStorageElement(const ModelStorageElement &)=default
friend H AbslHashValue(H h, const Derived &element)
friend std::ostream & operator<<(std::ostream &ostr, const Derived &element)
ModelStorageElement & operator=(const ModelStorageElement &)=default
friend std::enable_if_t< equality==ModelStorageElementEquality::kWithEquality, bool > operator==(const Derived &lhs, const Derived &rhs)
ElementId< element_type > IdType
The typed integer used for ids.
ModelStorageElement(ModelStorageElement &&)=default
ModelStorageElement & operator=(ModelStorageElement &&)=default
ModelStorageElement(ModelStorageCPtr storage, IdType id)
ModelStorageItemContainer(const NullableModelStorageCPtr storage=nullptr)
void SetOrCheckStorage(const ModelStorageItemContainer &container)
ModelStorageItemContainer(const ModelStorageItemContainer &other)=default
ModelStorageItemContainer & operator=(const ModelStorageItemContainer &other)=default
ModelStorageItemContainer & operator=(ModelStorageItemContainer &&other)
ModelStorageItem & operator=(ModelStorageItem &&)=default
ModelStorageItem & operator=(const ModelStorageItem &)=default
ModelStorageItem(const ModelStorageItem &)=default
ModelStorageItem(ModelStorageItem &&)=default
void FormatModelStorageElement(std::ostream &ostr, ElementType element_type, absl::string_view name, int64_t id)
An object oriented wrapper for quadratic constraints in ModelStorage.
Definition gurobi_isv.cc:28
absl::Nonnull< const ModelStorage * > ModelStorageCPtr
ModelStorageElementEquality
Whether ModelStorageElement should define equality operators.
absl::Nullable< const ModelStorage * > NullableModelStorageCPtr
STL namespace.