24#include "absl/algorithm/container.h"
25#include "absl/container/flat_hash_map.h"
26#include "absl/container/flat_hash_set.h"
27#include "absl/status/status.h"
28#include "absl/status/statusor.h"
29#include "absl/strings/str_format.h"
30#include "absl/strings/str_join.h"
31#include "absl/strings/string_view.h"
52constexpr double kInf = std::numeric_limits<double>::infinity();
56 return {.lower = bounds_proto.
lower(), .upper = bounds_proto.
upper()};
67 const auto bool_to_str = [](
const bool b) {
return b ?
"true" :
"false"; };
68 out <<
"{lower: " << bool_to_str(bounds.
lower)
69 <<
", upper: " << bool_to_str(bounds.
upper) <<
"}";
76absl::Status BoundsMapProtoToCpp(
77 const google::protobuf::Map<int64_t, ModelSubsetProto::Bounds>& source,
78 absl::flat_hash_map<K, ModelSubset::Bounds>& target,
80 bool (ModelStorage::*
const contains_strong_id)(
typename K::IdType
id)
82 const absl::string_view object_name) {
83 for (
const auto& [raw_id, bounds_proto] : source) {
84 const typename K::IdType strong_id(raw_id);
85 if (!(model->*contains_strong_id)(strong_id)) {
87 <<
"no " << object_name <<
" with id: " << raw_id;
92 return absl::OkStatus();
96absl::Status RepeatedIdsProtoToCpp(
97 const google::protobuf::RepeatedField<int64_t>& source,
99 bool (ModelStorage::*
const contains_strong_id)(
typename K::IdType
id)
101 const absl::string_view object_name) {
102 for (
const int64_t raw_id : source) {
103 const typename K::IdType strong_id(raw_id);
104 if (!(model->*contains_strong_id)(strong_id)) {
106 <<
"no " << object_name <<
" with id: " << raw_id;
108 target.insert(K(model, strong_id));
110 return absl::OkStatus();
114google::protobuf::Map<int64_t, ModelSubsetProto::Bounds> BoundsMapCppToProto(
115 const absl::flat_hash_map<K, ModelSubset::Bounds> source) {
116 google::protobuf::Map<int64_t, ModelSubsetProto::Bounds> result;
117 for (
const auto& [key, bounds] : source) {
118 result.insert({key.id(), bounds.Proto()});
124google::protobuf::RepeatedField<int64_t> RepeatedIdsCppToProto(
125 const absl::flat_hash_set<K>& source) {
126 google::protobuf::RepeatedField<int64_t> result;
127 for (
const auto object : source) {
128 result.Add(
object.
id());
130 absl::c_sort(result);
141 &ModelStorage::has_variable,
"variable"))
142 <<
"element of variable_bounds";
145 &ModelStorage::has_variable,
"variable"))
146 <<
"element of variable_integrality";
149 &ModelStorage::has_linear_constraint,
"linear constraint"));
152 &ModelStorage::has_constraint,
"quadratic constraint"));
156 &ModelStorage::has_constraint,
"second-order cone constraint"));
159 &ModelStorage::has_constraint,
"SOS1 constraint"));
162 &ModelStorage::has_constraint,
"SOS2 constraint"));
165 &ModelStorage::has_constraint,
"indicator constraint"));
188 const auto validate_map_keys =
189 [expected_storage](
const auto& map,
190 const absl::string_view name) -> absl::Status {
191 for (
const auto& [key, unused] : map) {
194 <<
"invalid key " << key <<
" in " << name;
196 return absl::OkStatus();
198 const auto validate_set_elements =
199 [expected_storage](
const auto& set,
200 const absl::string_view name) -> absl::Status {
201 for (
const auto entry : set) {
204 <<
"invalid entry " << entry <<
" in " << name;
206 return absl::OkStatus();
216 "second_order_cone_constraints"));
221 return absl::OkStatus();
232 std::stringstream str;
233 str <<
"Model Subset:\n";
234 const auto stream_object = [&str](
const auto& object) {
235 str <<
" " <<
object <<
": " <<
object.ToString() <<
"\n";
237 const auto stream_bounded_object =
240 if (bounds.empty()) {
249 const double lb = bounds.lower ? as_expr.lower_bound : -
kInf;
250 const double ub = bounds.upper ? as_expr.upper_bound :
kInf;
251 str <<
" " <<
object <<
": " << (lb <= as_expr.expression <= ub)
255 str <<
" Variable bounds:\n";
257 stream_bounded_object(
258 variable, variable.lower_bound() <= variable <= variable.upper_bound(),
261 str <<
" Variable integrality:\n";
263 str <<
" " << variable <<
"\n";
265 str <<
" Linear constraints:\n";
267 stream_bounded_object(constraint, constraint.AsBoundedLinearExpression(),
271 str <<
" Quadratic constraints:\n";
274 stream_bounded_object(constraint,
275 constraint.AsBoundedQuadraticExpression(),
280 str <<
" Second-order cone constraints:\n";
283 stream_object(constraint);
287 str <<
" SOS1 constraints:\n";
289 stream_object(constraint);
293 str <<
" SOS2 constraints:\n";
295 stream_object(constraint);
299 str <<
" Indicator constraints:\n";
302 stream_object(constraint);
309 const auto stream_bounds_map = [&out](
const auto& map,
310 const absl::string_view name) {
313 [map](std::string* out,
const auto& key) {
314 absl::StrAppendFormat(
315 out,
"{%s, %s}", absl::FormatStreamed(key),
316 absl::FormatStreamed(map.at(key)));
320 const auto stream_set = [&out](
const auto& set,
321 const absl::string_view name) {
323 << absl::StrJoin(
SortedElements(set),
", ", absl::StreamFormatter())
335 "quadratic_constraints");
338 "second_order_cone_constraints");
349absl::StatusOr<ComputeInfeasibleSubsystemResult>
354 const std::optional<FeasibilityStatus>
feasibility =
357 return absl::InvalidArgumentError(
358 "ComputeInfeasibleSubsystemResultProto.feasibility must be specified");
369 "ComputeInfeasibleSubsystemResultProto.infeasible_subsystem");
394 <<
", is_minimal: " << (result.
is_minimal ?
"true" :
"false") <<
"}";
#define RETURN_IF_ERROR(expr)
void set_feasibility(::operations_research::math_opt::FeasibilityStatusProto value)
void set_is_minimal(bool value)
const ::operations_research::math_opt::ModelSubsetProto & infeasible_subsystem() const
::operations_research::math_opt::FeasibilityStatusProto feasibility() const
::operations_research::math_opt::ModelSubsetProto *PROTOBUF_NONNULL mutable_infeasible_subsystem()
void set_upper(bool value)
void set_lower(bool value)
::google::protobuf::Map<::int64_t, ::operations_research::math_opt::ModelSubsetProto_Bounds > *PROTOBUF_NONNULL mutable_linear_constraints()
::google::protobuf::Map<::int64_t, ::operations_research::math_opt::ModelSubsetProto_Bounds > *PROTOBUF_NONNULL mutable_quadratic_constraints()
::int64_t variable_integrality(int index) const
const ::google::protobuf::Map<::int64_t, ::operations_research::math_opt::ModelSubsetProto_Bounds > & linear_constraints() const
::int64_t second_order_cone_constraints(int index) const
::int64_t sos1_constraints(int index) const
::int64_t sos2_constraints(int index) const
const ::google::protobuf::Map<::int64_t, ::operations_research::math_opt::ModelSubsetProto_Bounds > & quadratic_constraints() const
::google::protobuf::Map<::int64_t, ::operations_research::math_opt::ModelSubsetProto_Bounds > *PROTOBUF_NONNULL mutable_variable_bounds()
::google::protobuf::RepeatedField<::int64_t > *PROTOBUF_NONNULL mutable_second_order_cone_constraints()
::int64_t indicator_constraints(int index) const
::google::protobuf::RepeatedField<::int64_t > *PROTOBUF_NONNULL mutable_variable_integrality()
::google::protobuf::RepeatedField<::int64_t > *PROTOBUF_NONNULL mutable_indicator_constraints()
ModelSubsetProto_Bounds Bounds
nested types -------------------------------------------------—
const ::google::protobuf::Map<::int64_t, ::operations_research::math_opt::ModelSubsetProto_Bounds > & variable_bounds() const
::google::protobuf::RepeatedField<::int64_t > *PROTOBUF_NONNULL mutable_sos2_constraints()
::google::protobuf::RepeatedField<::int64_t > *PROTOBUF_NONNULL mutable_sos1_constraints()
absl::Status CheckModelStorage(const NullableModelStorageCPtr storage, const ModelStorageCPtr expected_storage)
An object oriented wrapper for quadratic constraints in ModelStorage.
absl::Nonnull< const ModelStorage * > ModelStorageCPtr
std::vector< typename Set::key_type > SortedElements(const Set &set)
std::optional< typename EnumProto< P >::Cpp > EnumFromProto(P proto_value)
std::ostream & operator<<(std::ostream &ostr, const SecondOrderConeConstraint &constraint)
Enum< E >::Proto EnumToProto(std::optional< E > value)
absl::Status ValidateComputeInfeasibleSubsystemResultNoModel(const ComputeInfeasibleSubsystemResultProto &result)
Validates the internal consistency of the fields.
std::vector< typename Map::key_type > SortedKeys(const Map &map)
StatusBuilder InvalidArgumentErrorBuilder()
A QuadraticExpression with upper and lower bounds.
absl::Status CheckModelStorage(ModelStorageCPtr expected_storage) const
ModelSubset infeasible_subsystem
FeasibilityStatus feasibility
The primal feasibility status of the model, as determined by the solver.
ComputeInfeasibleSubsystemResultProto Proto() const
static absl::StatusOr< ComputeInfeasibleSubsystemResult > FromProto(ModelStorageCPtr model, const ComputeInfeasibleSubsystemResultProto &result_proto)
ModelSubsetProto::Bounds Proto() const
static Bounds FromProto(const ModelSubsetProto::Bounds &bounds_proto)
absl::flat_hash_map< Variable, Bounds > variable_bounds
absl::flat_hash_set< SecondOrderConeConstraint > second_order_cone_constraints
absl::flat_hash_set< Variable > variable_integrality
bool empty() const
True if this object corresponds to the empty subset.
absl::flat_hash_set< Sos1Constraint > sos1_constraints
ModelSubsetProto Proto() const
static absl::StatusOr< ModelSubset > FromProto(ModelStorageCPtr model, const ModelSubsetProto &proto)
absl::flat_hash_map< LinearConstraint, Bounds > linear_constraints
std::string ToString() const
absl::flat_hash_set< IndicatorConstraint > indicator_constraints
absl::Status CheckModelStorage(ModelStorageCPtr expected_storage) const
absl::flat_hash_map< QuadraticConstraint, Bounds > quadratic_constraints
absl::flat_hash_set< Sos2Constraint > sos2_constraints
#define OR_ASSIGN_OR_RETURN3(lhs, rexpr, error_expression)