14#ifndef OR_TOOLS_MATH_OPT_STORAGE_MODEL_STORAGE_V2_H_
15#define OR_TOOLS_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"
41#include "ortools/math_opt/model.pb.h"
42#include "ortools/math_opt/model_update.pb.h"
43#include "ortools/math_opt/sparse_containers.pb.h"
93 static absl::StatusOr<absl::Nonnull<std::unique_ptr<ModelStorageV2>>>
98 absl::string_view primary_objective_name =
"");
109 absl::Nonnull<std::unique_ptr<ModelStorageV2>>
Clone(
110 std::optional<absl::string_view> new_name = std::nullopt)
const;
112 inline const std::string&
name()
const {
return elemental_.model_name(); }
129 bool is_integer, absl::string_view
name =
"");
170 std::vector<VariableId>
Variables()
const;
195 absl::string_view
name =
"");
259 inline std::vector<std::tuple<LinearConstraintId, VariableId, double>>
354 int64_t priority,
absl::string_view
name =
"");
406 template <typename ConstraintData>
408 ConstraintData data);
414 template <typename IdType>
418 template <typename IdType>
424 template <typename IdType>
433 template <typename IdType>
438 template <typename IdType>
444 template <typename IdType>
448 template <typename IdType>
452 template <typename IdType>
460 template <typename IdType>
466 template <typename IdType>
472 template <typename IdType>
492 return *std::move(result);
535 UpdateTrackerId update_tracker,
bool remove_names =
false)
const;
539 const UpdateTrackerId update_tracker,
540 const
bool remove_names =
false)
const {
543 return *std::move(result);
569 : elemental_(
std::move(elemental)) {
570 CHECK_EQ(elemental_.NumDiffs(), 0);
583 const absl::string_view primary_objective_name)
584 : elemental_(
std::string(model_name),
std::string(primary_objective_name)) {
597 const double upper_bound,
598 const bool is_integer,
599 const absl::string_view name) {
608 return elemental_.
GetAttr(DoubleAttr1::kVarLb,
AttrKey(
id.value()));
612 return elemental_.GetAttr(DoubleAttr1::kVarUb,
AttrKey(
id.value()));
616 return elemental_.GetAttr(BoolAttr1::kVarInteger,
AttrKey(
id.value()));
626 const double lower_bound) {
627 elemental_.SetAttr(DoubleAttr1::kVarLb,
AttrKey(
id.value()), lower_bound);
631 const double upper_bound) {
632 elemental_.SetAttr(DoubleAttr1::kVarUb,
AttrKey(
id.value()), upper_bound);
636 const bool is_integer) {
637 elemental_.SetAttr(BoolAttr1::kVarInteger,
AttrKey(
id.value()), is_integer);
657 elemental_.EnsureNextElementIdAtLeast(
id);
661 return elemental_.ElementExists(
id);
669 const absl::string_view
name) {
674 const double lower_bound,
const double upper_bound,
675 const absl::string_view
name) {
684 return elemental_.
GetAttr(DoubleAttr1::kLinConLb,
AttrKey(
id.value()));
689 return elemental_.
GetAttr(DoubleAttr1::kLinConUb,
AttrKey(
id.value()));
701 elemental_.
SetAttr(DoubleAttr1::kLinConLb,
AttrKey(
id.value()), lower_bound);
706 elemental_.SetAttr(DoubleAttr1::kLinConUb,
AttrKey(
id.value()), upper_bound);
733 return elemental_.GetAttr(DoubleAttr2::kLinConCoef,
745 const double value) {
746 elemental_.SetAttr(DoubleAttr2::kLinConCoef,
750std::vector<std::tuple<LinearConstraintId, VariableId, double>>
752 std::vector<std::tuple<LinearConstraintId, VariableId, double>> result;
754 for (
const auto attr_key :
755 elemental_.AttrNonDefaults(DoubleAttr2::kLinConCoef)) {
757 elemental_.GetAttr(DoubleAttr2::kLinConCoef, attr_key)});
764 const std::vector<AttrKeyFor<DoubleAttr2>> slice =
765 elemental_.Slice<0>(DoubleAttr2::kLinConCoef, constraint.
value());
766 std::vector<VariableId> result;
767 result.reserve(slice.size());
768 for (
const auto key : slice) {
774std::vector<LinearConstraintId>
777 const std::vector<AttrKeyFor<DoubleAttr2>> slice =
778 elemental_.Slice<1>(DoubleAttr2::kLinConCoef, variable.
value());
779 std::vector<LinearConstraintId> result;
780 result.reserve(slice.size());
781 for (
const auto key : slice) {
792 return id.has_value() ? elemental_.GetAttr(BoolAttr1::kAuxObjMaximize,
794 : elemental_.GetAttr(BoolAttr0::kMaximize,
AttrKey());
798 return id.has_value() ? elemental_.
GetAttr(IntAttr1::kAuxObjPriority,
800 : elemental_.GetAttr(IntAttr0::kObjPriority,
AttrKey());
804 return id.has_value()
805 ? elemental_.
GetAttr(DoubleAttr1::kAuxObjOffset,
812 return id.has_value()
813 ? elemental_.
GetAttr(DoubleAttr2::kAuxObjLinCoef,
814 AttrKey(id->value(), variable.value()))
815 : elemental_.
GetAttr(DoubleAttr1::kObjLinCoef,
822 CHECK(!
id.has_value()) <<
"multiple objectives not supported";
823 return elemental_.GetAttr(
824 SymmetricDoubleAttr2::kObjQuadCoef,
826 second_variable.
value()));
831 return id.has_value()
832 ? elemental_.AttrIsNonDefault(
833 DoubleAttr2::kAuxObjLinCoef,
835 : elemental_.AttrIsNonDefault(DoubleAttr1::kObjLinCoef,
842 CHECK(!
id.has_value()) <<
"multiple objectives not supported";
844 SymmetricDoubleAttr2::kObjQuadCoef,
846 second_variable.
value()));
858 const bool is_maximize) {
859 if (
id.has_value()) {
860 elemental_.
SetAttr(BoolAttr1::kAuxObjMaximize,
AttrKey(id->value()),
876 const int64_t value) {
877 if (
id.has_value()) {
878 elemental_.SetAttr(IntAttr1::kAuxObjPriority,
AttrKey(id->value()), value);
880 elemental_.SetAttr(IntAttr0::kObjPriority,
AttrKey(), value);
885 const double value) {
886 if (
id.has_value()) {
887 elemental_.SetAttr(DoubleAttr1::kAuxObjOffset,
AttrKey(id->value()), value);
889 elemental_.SetAttr(DoubleAttr0::kObjOffset,
AttrKey(), value);
895 const double value) {
896 if (
id.has_value()) {
897 elemental_.SetAttr(DoubleAttr2::kAuxObjLinCoef,
907 const VariableId second_variable,
const double value) {
908 CHECK(!
id.has_value()) <<
"multiple objectives not supported";
909 elemental_.
SetAttr(SymmetricDoubleAttr2::kObjQuadCoef,
911 second_variable.value()),
916 if (
id.has_value()) {
918 elemental_.
SetAttr(IntAttr1::kAuxObjPriority,
AttrKey(id->value()),
920 elemental_.SetAttr(DoubleAttr1::kAuxObjOffset,
AttrKey(id->value()),
923 for (
const auto key :
924 elemental_.Slice<0>(DoubleAttr2::kAuxObjLinCoef, id->value())) {
925 elemental_.SetAttr(DoubleAttr2::kAuxObjLinCoef, key,
929 elemental_.
AttrClear(IntAttr0::kObjPriority);
930 elemental_.
AttrClear(DoubleAttr0::kObjOffset);
931 elemental_.AttrClear(DoubleAttr1::kObjLinCoef);
937 LOG(FATAL) <<
"cannot be implemented";
941 if (
id.has_value()) {
942 return elemental_.GetSliceSize<0>(DoubleAttr2::kAuxObjLinCoef,
id->value());
950 CHECK(!
id.has_value()) <<
"multiple objectives not supported";
954std::vector<std::tuple<VariableId, VariableId, double>>
956 CHECK(!
id.has_value()) <<
"multiple objectives not supported";
957 std::vector<std::tuple<VariableId, VariableId, double>> result;
959 elemental_.AttrNumNonDefaults(SymmetricDoubleAttr2::kObjQuadCoef));
960 for (
const auto attr_key :
961 elemental_.AttrNonDefaults(SymmetricDoubleAttr2::kObjQuadCoef)) {
964 elemental_.GetAttr(SymmetricDoubleAttr2::kObjQuadCoef, attr_key)});
974 const int64_t priority,
const absl::string_view
name) {
976 elemental_.SetAttr(IntAttr1::kAuxObjPriority,
AttrKey(
id), priority);
981 CHECK(elemental_.DeleteElement(
id)) <<
"no auxiliary objective " << id;
985 return static_cast<int>(
1001 return elemental_.ElementExists(
id);
1006 std::vector<AuxiliaryObjectiveId> result;
1007 result.reserve(ids.size());
1008 for (
const auto id : ids) {
1009 result.emplace_back(
id);
1025template <
typename Constra
intData>
1027 const ConstraintData data) {
1028 if constexpr (!ConstraintData::kSupportsElemental) {
1029 LOG(FATAL) <<
"elemental not supported yet";
1035template <
typename IdType>
1037 if constexpr (!AtomicConstraintTraits<IdType>::kSupportsElemental) {
1038 LOG(FATAL) <<
"elemental not supported yet";
1041 <<
"no constraint in the model with id: " << id;
1045template <
typename IdType>
1048 if constexpr (!AtomicConstraintTraits<IdType>::kSupportsElemental) {
1049 LOG(FATAL) <<
"elemental not supported yet";
1055template <
typename IdType>
1058 LOG(FATAL) <<
"not implementable for ModelStorageV2";
1061template <
typename IdType>
1064 LOG(FATAL) <<
"elemental not supported yet";
1070template <
typename IdType>
1072 if constexpr (!AtomicConstraintTraits<IdType>::kSupportsElemental) {
1073 LOG(FATAL) <<
"elemental not supported yet";
1076 elemental_.
NextElementId(AtomicConstraintTraits<IdType>::kElementType)};
1080template <
typename IdType>
1082 if constexpr (!AtomicConstraintTraits<IdType>::kSupportsElemental) {
1083 LOG(FATAL) <<
"elemental not supported yet";
1089template <
typename IdType>
1092 LOG(FATAL) <<
"elemental not supported yet";
1098template <
typename IdType>
1100 if constexpr (!AtomicConstraintTraits<IdType>::kSupportsElemental) {
1101 LOG(FATAL) <<
"elemental not supported yet";
1105 std::vector<ElementId<e>> result;
1106 result.reserve(els.size());
1108 result.push_back(el);
1114template <
typename IdType>
1116 if constexpr (!AtomicConstraintTraits<IdType>::kSupportsElemental) {
1117 LOG(FATAL) <<
"elemental not supported yet";
1120 absl::c_sort(result);
1125template <
typename IdType>
1128 LOG(FATAL) <<
"not implementable for ModelStorageV2";
1131template <
typename IdType>
1133 const IdType)
const {
1134 LOG(FATAL) <<
"not implementable for ModelStorageV2";
A strongly typed element id. Value type.
int64_t value() const
Returns the raw id value.
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
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< 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)
Inline and template implementation.
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)
Creates and returns the id of a new element for the element type e.
int64_t NextElementId(const ElementType e) const
int64_t NumElements(const ElementType e) const
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
Returns true if this id has been created and not yet deleted.
std::vector< VariableId > VariablesInConstraint(IdType id) const
Returns the variables appearing in the constraint. Order is not defined.
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
static absl::StatusOr< absl::Nonnull< std::unique_ptr< ModelStorageV2 > > > FromModelProto(const ModelProto &model_proto)
int64_t num_linear_objective_terms(ObjectiveId id) const
const AtomicConstraintTraits< IdType >::ConstraintData & constraint_data(IdType id) const
Accesses the data object that fully represents a single atomic constraint.
void ensure_next_variable_id_at_least(VariableId id)
Sets the next variable id to be the maximum of next_variable_id() and id.
bool has_constraint(IdType id) const
Returns true if this id has been created and not yet deleted.
std::vector< LinearConstraintId > LinearConstraints() const
The LinearConstraintsIds in use (not deleted), order not defined.
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
The ordering of the input variables does not matter.
void DeleteVariable(VariableId id)
int64_t objective_priority(ObjectiveId id) const
std::vector< VariableId > Variables() const
The VariableIds in use (not deleted), order not defined.
bool has_linear_constraint(LinearConstraintId id) const
Returns true if this id has been created and not yet deleted.
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
Returns true if this id has been created and not yet deleted.
double linear_objective_coefficient(ObjectiveId id, VariableId variable) const
Returns 0.0 if this variable has no linear objective coefficient.
ModelStorageV2(absl::string_view model_name="", absl::string_view primary_objective_name="")
Creates an empty minimization problem.
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
Returns 0.0 if the entry is not in matrix.
ModelStorageV2 & operator=(const ModelStorageV2 &)=delete
void set_is_maximize(ObjectiveId id, bool is_maximize)
AuxiliaryObjectiveId next_auxiliary_objective_id() const
void ensure_next_auxiliary_objective_id_at_least(AuxiliaryObjectiveId id)
double quadratic_objective_coefficient(ObjectiveId id, VariableId first_variable, VariableId second_variable) const
The ordering of the input variables does not matter.
std::vector< IdType > Constraints() const
Returns the constraint IDs in use (not deleted); order is not defined.
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
Returns the variables with nonzero coefficients in a linear constraint.
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
The AuxiliaryObjectiveIds in use (not deleted), order not defined.
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
The variables with nonzero linear objective coefficients.
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)
absl::Nonnull< std::unique_ptr< ModelStorageV2 > > Clone(std::optional< absl::string_view > new_name=std::nullopt) const
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
Returns the linear constraints with nonzero coefficients on a variable.
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)
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.
For infeasible and unbounded see Not checked if options check_solutions_if_inf_or_unbounded and the If options first_solution_only is false
problem is infeasible or unbounded (default).
ElementId< ElementType::kAuxiliaryObjective > AuxiliaryObjectiveId
ElementId< ElementType::kVariable > VariableId
AttrKey(Ints... dims) -> AttrKey< sizeof...(Ints), NoSymmetry >
CTAD for AttrKey(1,2).
ElementId< ElementType::kLinearConstraint > LinearConstraintId
std::optional< AuxiliaryObjectiveId > ObjectiveId
nullopt denotes the primary objective.
constexpr AttrTypeDescriptorT< decltype(attr)>::ValueType GetAttrDefaultValue()
ABSL_DEPRECATED("Use TerminateForReason(bool, TerminationReasonProto, absl::string_view) " "instead") TerminationProto TerminateForReason(TerminationReasonProto reason