14#ifndef ORTOOLS_MATH_OPT_STORAGE_MODEL_STORAGE_V2_H_
15#define ORTOOLS_MATH_OPT_STORAGE_MODEL_STORAGE_V2_H_
25#include "absl/algorithm/container.h"
26#include "absl/base/nullability.h"
27#include "absl/container/flat_hash_map.h"
28#include "absl/log/check.h"
29#include "absl/log/log.h"
30#include "absl/status/status.h"
31#include "absl/status/statusor.h"
32#include "absl/strings/string_view.h"
90 static absl::StatusOr<absl_nonnull std::unique_ptr<ModelStorageV2>>
95 absl::string_view primary_objective_name =
"");
106 absl_nonnull std::unique_ptr<ModelStorageV2>
Clone(
107 std::optional<absl::string_view> new_name = std::nullopt)
const;
109 inline const std::string&
name()
const {
return elemental_.model_name(); }
126 bool is_integer, absl::string_view
name =
"");
167 std::vector<VariableId>
Variables()
const;
192 absl::string_view
name =
"");
256 inline std::vector<std::tuple<LinearConstraintId, VariableId, double>>
351 int64_t priority,
absl::string_view
name =
"");
403 template <typename ConstraintData>
405 ConstraintData data);
411 template <typename IdType>
415 template <typename IdType>
421 template <typename IdType>
430 template <typename IdType>
435 template <typename IdType>
441 template <typename IdType>
445 template <typename IdType>
449 template <typename IdType>
457 template <typename IdType>
463 template <typename IdType>
469 template <typename IdType>
489 return *std::move(result);
532 UpdateTrackerId update_tracker,
bool remove_names =
false)
const;
536 const UpdateTrackerId update_tracker,
537 const
bool remove_names =
false)
const {
540 return *std::move(result);
566 : elemental_(
std::move(elemental)) {
567 CHECK_EQ(elemental_.NumDiffs(), 0);
580 const absl::string_view primary_objective_name)
581 : elemental_(
std::string(model_name),
std::string(primary_objective_name)) {
594 const double upper_bound,
595 const bool is_integer,
596 const absl::string_view name) {
605 return elemental_.
GetAttr(DoubleAttr1::kVarLb,
AttrKey(
id.value()));
609 return elemental_.GetAttr(DoubleAttr1::kVarUb,
AttrKey(
id.value()));
613 return elemental_.GetAttr(BoolAttr1::kVarInteger,
AttrKey(
id.value()));
623 const double lower_bound) {
624 elemental_.SetAttr(DoubleAttr1::kVarLb,
AttrKey(
id.value()), lower_bound);
628 const double upper_bound) {
629 elemental_.SetAttr(DoubleAttr1::kVarUb,
AttrKey(
id.value()), upper_bound);
633 const bool is_integer) {
634 elemental_.SetAttr(BoolAttr1::kVarInteger,
AttrKey(
id.value()), is_integer);
654 elemental_.EnsureNextElementIdAtLeast(
id);
658 return elemental_.ElementExists(
id);
666 const absl::string_view
name) {
671 const double lower_bound,
const double upper_bound,
672 const absl::string_view
name) {
681 return elemental_.
GetAttr(DoubleAttr1::kLinConLb,
AttrKey(
id.value()));
686 return elemental_.
GetAttr(DoubleAttr1::kLinConUb,
AttrKey(
id.value()));
698 elemental_.
SetAttr(DoubleAttr1::kLinConLb,
AttrKey(
id.value()), lower_bound);
703 elemental_.SetAttr(DoubleAttr1::kLinConUb,
AttrKey(
id.value()), upper_bound);
730 return elemental_.GetAttr(DoubleAttr2::kLinConCoef,
742 const double value) {
743 elemental_.SetAttr(DoubleAttr2::kLinConCoef,
747std::vector<std::tuple<LinearConstraintId, VariableId, double>>
749 std::vector<std::tuple<LinearConstraintId, VariableId, double>> result;
751 for (
const auto attr_key :
752 elemental_.AttrNonDefaults(DoubleAttr2::kLinConCoef)) {
754 elemental_.GetAttr(DoubleAttr2::kLinConCoef, attr_key)});
761 const std::vector<AttrKeyFor<DoubleAttr2>> slice =
762 elemental_.Slice<0>(DoubleAttr2::kLinConCoef, constraint.
value());
763 std::vector<VariableId> result;
764 result.reserve(slice.size());
765 for (
const auto key : slice) {
771std::vector<LinearConstraintId>
774 const std::vector<AttrKeyFor<DoubleAttr2>> slice =
775 elemental_.Slice<1>(DoubleAttr2::kLinConCoef, variable.
value());
776 std::vector<LinearConstraintId> result;
777 result.reserve(slice.size());
778 for (
const auto key : slice) {
789 return id.has_value() ? elemental_.GetAttr(BoolAttr1::kAuxObjMaximize,
791 : elemental_.GetAttr(BoolAttr0::kMaximize,
AttrKey());
795 return id.has_value() ? elemental_.
GetAttr(IntAttr1::kAuxObjPriority,
797 : elemental_.GetAttr(IntAttr0::kObjPriority,
AttrKey());
801 return id.has_value()
802 ? elemental_.
GetAttr(DoubleAttr1::kAuxObjOffset,
809 return id.has_value()
810 ? elemental_.
GetAttr(DoubleAttr2::kAuxObjLinCoef,
811 AttrKey(id->value(), variable.value()))
812 : elemental_.
GetAttr(DoubleAttr1::kObjLinCoef,
819 CHECK(!
id.has_value()) <<
"multiple objectives not supported";
820 return elemental_.GetAttr(
821 SymmetricDoubleAttr2::kObjQuadCoef,
823 second_variable.
value()));
828 return id.has_value()
829 ? elemental_.AttrIsNonDefault(
830 DoubleAttr2::kAuxObjLinCoef,
832 : elemental_.AttrIsNonDefault(DoubleAttr1::kObjLinCoef,
839 CHECK(!
id.has_value()) <<
"multiple objectives not supported";
841 SymmetricDoubleAttr2::kObjQuadCoef,
843 second_variable.
value()));
855 const bool is_maximize) {
856 if (
id.has_value()) {
857 elemental_.
SetAttr(BoolAttr1::kAuxObjMaximize,
AttrKey(id->value()),
873 const int64_t value) {
874 if (
id.has_value()) {
875 elemental_.SetAttr(IntAttr1::kAuxObjPriority,
AttrKey(id->value()), value);
877 elemental_.SetAttr(IntAttr0::kObjPriority,
AttrKey(), value);
882 const double value) {
883 if (
id.has_value()) {
884 elemental_.SetAttr(DoubleAttr1::kAuxObjOffset,
AttrKey(id->value()), value);
886 elemental_.SetAttr(DoubleAttr0::kObjOffset,
AttrKey(), value);
892 const double value) {
893 if (
id.has_value()) {
894 elemental_.SetAttr(DoubleAttr2::kAuxObjLinCoef,
904 const VariableId second_variable,
const double value) {
905 CHECK(!
id.has_value()) <<
"multiple objectives not supported";
906 elemental_.
SetAttr(SymmetricDoubleAttr2::kObjQuadCoef,
908 second_variable.value()),
913 if (
id.has_value()) {
915 elemental_.
SetAttr(IntAttr1::kAuxObjPriority,
AttrKey(id->value()),
917 elemental_.SetAttr(DoubleAttr1::kAuxObjOffset,
AttrKey(id->value()),
920 for (
const auto key :
921 elemental_.Slice<0>(DoubleAttr2::kAuxObjLinCoef, id->value())) {
922 elemental_.SetAttr(DoubleAttr2::kAuxObjLinCoef, key,
926 elemental_.
AttrClear(IntAttr0::kObjPriority);
927 elemental_.
AttrClear(DoubleAttr0::kObjOffset);
928 elemental_.AttrClear(DoubleAttr1::kObjLinCoef);
934 LOG(FATAL) <<
"cannot be implemented";
938 if (
id.has_value()) {
939 return elemental_.GetSliceSize<0>(DoubleAttr2::kAuxObjLinCoef,
id->value());
947 CHECK(!
id.has_value()) <<
"multiple objectives not supported";
951std::vector<std::tuple<VariableId, VariableId, double>>
953 CHECK(!
id.has_value()) <<
"multiple objectives not supported";
954 std::vector<std::tuple<VariableId, VariableId, double>> result;
956 elemental_.AttrNumNonDefaults(SymmetricDoubleAttr2::kObjQuadCoef));
957 for (
const auto attr_key :
958 elemental_.AttrNonDefaults(SymmetricDoubleAttr2::kObjQuadCoef)) {
961 elemental_.GetAttr(SymmetricDoubleAttr2::kObjQuadCoef, attr_key)});
971 const int64_t priority,
const absl::string_view
name) {
973 elemental_.SetAttr(IntAttr1::kAuxObjPriority,
AttrKey(
id), priority);
978 CHECK(elemental_.DeleteElement(
id)) <<
"no auxiliary objective " << id;
982 return static_cast<int>(
998 return elemental_.ElementExists(
id);
1003 std::vector<AuxiliaryObjectiveId> result;
1004 result.reserve(ids.size());
1005 for (
const auto id : ids) {
1006 result.emplace_back(
id);
1022template <
typename Constra
intData>
1024 const ConstraintData data) {
1025 if constexpr (!ConstraintData::kSupportsElemental) {
1026 LOG(FATAL) <<
"elemental not supported yet";
1032template <
typename IdType>
1034 if constexpr (!AtomicConstraintTraits<IdType>::kSupportsElemental) {
1035 LOG(FATAL) <<
"elemental not supported yet";
1038 <<
"no constraint in the model with id: " << id;
1042template <
typename IdType>
1045 if constexpr (!AtomicConstraintTraits<IdType>::kSupportsElemental) {
1046 LOG(FATAL) <<
"elemental not supported yet";
1052template <
typename IdType>
1055 LOG(FATAL) <<
"not implementable for ModelStorageV2";
1058template <
typename IdType>
1061 LOG(FATAL) <<
"elemental not supported yet";
1067template <
typename IdType>
1069 if constexpr (!AtomicConstraintTraits<IdType>::kSupportsElemental) {
1070 LOG(FATAL) <<
"elemental not supported yet";
1073 elemental_.
NextElementId(AtomicConstraintTraits<IdType>::kElementType)};
1077template <
typename IdType>
1079 if constexpr (!AtomicConstraintTraits<IdType>::kSupportsElemental) {
1080 LOG(FATAL) <<
"elemental not supported yet";
1086template <
typename IdType>
1089 LOG(FATAL) <<
"elemental not supported yet";
1095template <
typename IdType>
1097 if constexpr (!AtomicConstraintTraits<IdType>::kSupportsElemental) {
1098 LOG(FATAL) <<
"elemental not supported yet";
1102 std::vector<ElementId<e>> result;
1103 result.reserve(els.size());
1105 result.push_back(el);
1111template <
typename IdType>
1113 if constexpr (!AtomicConstraintTraits<IdType>::kSupportsElemental) {
1114 LOG(FATAL) <<
"elemental not supported yet";
1117 absl::c_sort(result);
1122template <
typename IdType>
1125 LOG(FATAL) <<
"not implementable for ModelStorageV2";
1128template <
typename IdType>
1130 const IdType)
const {
1131 LOG(FATAL) <<
"not implementable for ModelStorageV2";
Policy::CheckResultT SetAttr(AttrType a, AttrKeyFor< AttrType > key, ValueTypeFor< AttrType > value)
bool ElementExists(const ElementId< e > id) const
int64_t AttrNumNonDefaults(const AttrType a) const
const std::string & primary_objective_name() const
absl::StatusOr< absl::string_view > GetElementName(const ElementId< e > id) const
bool DeleteElement(const ElementId< e > id)
Policy::template Wrapped< bool > AttrIsNonDefault(AttrType a, AttrKeyFor< AttrType > key) const
void AttrClear(AttrType a)
Policy::template Wrapped< ValueTypeFor< AttrType > > GetAttr(AttrType a, AttrKeyFor< AttrType > key) const
ElementIdsVector< e > AllElements() const
void EnsureNextElementIdAtLeast(const ElementId< e > id)
ElementId< e > AddElement(const absl::string_view name)
int64_t NextElementId(const ElementType e) const
int64_t NumElements(const ElementType e) const
static absl::StatusOr< absl_nonnull std::unique_ptr< ModelStorageV2 > > FromModelProto(const ModelProto &model_proto)
const std::string & name() const
void set_linear_constraint_lower_bound(LinearConstraintId id, double lower_bound)
std::vector< VariableId > variables() const
double linear_constraint_lower_bound(LinearConstraintId id) const
bool has_auxiliary_objective(AuxiliaryObjectiveId id) const
std::vector< VariableId > VariablesInConstraint(IdType id) const
void ensure_next_linear_constraint_id_at_least(LinearConstraintId id)
absl::Status ApplyUpdateProto(const ModelUpdateProto &update_proto)
void set_objective_priority(ObjectiveId id, int64_t value)
void DeleteUpdateTracker(UpdateTrackerId update_tracker)
ModelStorageV2(const ModelStorageV2 &)=delete
void set_minimize(ObjectiveId id)
std::vector< IdType > ConstraintsWithVariable(VariableId variable_id) const
double variable_upper_bound(VariableId id) const
VariableId next_variable_id() const
int num_auxiliary_objectives() const
absl::string_view linear_constraint_name(LinearConstraintId id) const
int64_t num_linear_objective_terms(ObjectiveId id) const
const AtomicConstraintTraits< IdType >::ConstraintData & constraint_data(IdType id) const
void ensure_next_variable_id_at_least(VariableId id)
bool has_constraint(IdType id) const
std::vector< LinearConstraintId > LinearConstraints() const
IdType next_constraint_id() const
void set_maximize(ObjectiveId id)
bool is_variable_integer(VariableId id) const
void set_linear_constraint_coefficient(LinearConstraintId constraint, VariableId variable, double value)
bool is_quadratic_objective_coefficient_nonzero(ObjectiveId id, VariableId first_variable, VariableId second_variable) const
void DeleteVariable(VariableId id)
int64_t objective_priority(ObjectiveId id) const
std::vector< VariableId > Variables() const
bool has_linear_constraint(LinearConstraintId id) const
UpdateTrackerId NewUpdateTracker()
void set_linear_constraint_upper_bound(LinearConstraintId id, double upper_bound)
void set_quadratic_objective_coefficient(ObjectiveId id, VariableId first_variable, VariableId second_variable, double value)
void clear_objective(ObjectiveId id)
std::vector< VariableId > LinearObjectiveNonzeros(ObjectiveId id) const
void DeleteAtomicConstraint(IdType id)
bool has_variable(VariableId id) const
double linear_objective_coefficient(ObjectiveId id, VariableId variable) const
ModelStorageV2(absl::string_view model_name="", absl::string_view primary_objective_name="")
double variable_lower_bound(VariableId id) const
LinearConstraintId next_linear_constraint_id() const
void set_variable_lower_bound(VariableId id, double lower_bound)
void set_objective_offset(ObjectiveId id, double value)
bool is_maximize(ObjectiveId id) const
int64_t num_quadratic_objective_terms(ObjectiveId id) const
std::vector< AuxiliaryObjectiveId > SortedAuxiliaryObjectives() const
double linear_constraint_coefficient(LinearConstraintId constraint, VariableId variable) const
ModelStorageV2 & operator=(const ModelStorageV2 &)=delete
void set_is_maximize(ObjectiveId id, bool is_maximize)
AuxiliaryObjectiveId next_auxiliary_objective_id() const
absl_nonnull std::unique_ptr< ModelStorageV2 > Clone(std::optional< absl::string_view > new_name=std::nullopt) const
void ensure_next_auxiliary_objective_id_at_least(AuxiliaryObjectiveId id)
double quadratic_objective_coefficient(ObjectiveId id, VariableId first_variable, VariableId second_variable) const
std::vector< IdType > Constraints() const
void set_variable_as_integer(VariableId id)
void AdvanceCheckpoint(UpdateTrackerId update_tracker)
VariableId AddVariable(absl::string_view name="")
absl::StatusOr< ModelProto > ExportModelV2(bool remove_names=false) const
absl::string_view variable_name(VariableId id) const
std::vector< LinearConstraintId > SortedLinearConstraints() const
void DeleteLinearConstraint(LinearConstraintId id)
std::vector< VariableId > variables_in_linear_constraint(LinearConstraintId constraint) const
void DeleteAuxiliaryObjective(AuxiliaryObjectiveId id)
void set_variable_upper_bound(VariableId id, double upper_bound)
std::vector< std::tuple< LinearConstraintId, VariableId, double > > linear_constraint_matrix() const
AuxiliaryObjectiveId AddAuxiliaryObjective(int64_t priority, absl::string_view name="")
std::vector< AuxiliaryObjectiveId > AuxiliaryObjectives() const
std::optional< ModelUpdateProto > ExportModelUpdate(const UpdateTrackerId update_tracker, const bool remove_names=false) const
bool is_linear_objective_coefficient_nonzero(ObjectiveId id, VariableId variable) const
std::vector< VariableId > SortedVariables() const
std::vector< std::tuple< VariableId, VariableId, double > > quadratic_objective_terms(ObjectiveId id) const
const absl::flat_hash_map< VariableId, double > & linear_objective(ObjectiveId id) const
double linear_constraint_upper_bound(LinearConstraintId id) const
int64_t num_constraints() const
int64_t num_linear_constraints() const
ModelProto ExportModel(const bool remove_names=false) const
void ensure_next_constraint_id_at_least(IdType id)
int64_t num_variables() const
void set_variable_is_integer(VariableId id, bool is_integer)
void set_variable_as_continuous(VariableId id)
bool is_linear_constraint_coefficient_nonzero(LinearConstraintId constraint, VariableId variable) const
AtomicConstraintTraits< IdType >::ConstraintData GetConstraintData(IdType id) const
double objective_offset(ObjectiveId id) const
LinearConstraintId AddLinearConstraint(absl::string_view name="")
std::vector< LinearConstraintId > linear_constraints_with_variable(VariableId variable) const
void set_linear_objective_coefficient(ObjectiveId id, VariableId variable, double value)
ConstraintData::IdType AddAtomicConstraint(ConstraintData data)
absl::StatusOr< std::optional< ModelUpdateProto > > ExportModelUpdateV2(UpdateTrackerId update_tracker, bool remove_names=false) const
std::vector< IdType > SortedConstraints() const
absl::string_view objective_name(ObjectiveId id) const
AtomicConstraintTraits< ElementId< e > >::ConstraintData GetAtomicConstraint(ElementId< e > id, const Elemental &elemental)
ConstraintData::IdType AddAtomicConstraint(const ConstraintData &data, Elemental &elemental)
AttrKey< AttrTypeDescriptorT< AttrType >::kNumKeyElements, typename AttrTypeDescriptorT< AttrType >::Symmetry > AttrKeyFor
For infeasible and unbounded see Not checked if options check_solutions_if_inf_or_unbounded and the If options first_solution_only is false
ElementId< ElementType::kAuxiliaryObjective > AuxiliaryObjectiveId
ElementId< ElementType::kVariable > VariableId
AttrKey(Ints... dims) -> AttrKey< sizeof...(Ints), NoSymmetry >
ElementId< ElementType::kLinearConstraint > LinearConstraintId
TaggedId< element_type > ElementId
std::optional< AuxiliaryObjectiveId > ObjectiveId
constexpr AttrTypeDescriptorT< decltype(attr)>::ValueType GetAttrDefaultValue()
ABSL_DEPRECATED("Use TerminateForReason(bool, TerminationReasonProto, absl::string_view) " "instead") TerminationProto TerminateForReason(TerminationReasonProto reason