112 #ifndef OR_TOOLS_MATH_OPT_INDEXED_MODEL_H_
113 #define OR_TOOLS_MATH_OPT_INDEXED_MODEL_H_
121 #include "absl/container/flat_hash_map.h"
122 #include "absl/container/flat_hash_set.h"
123 #include "absl/meta/type_traits.h"
124 #include "absl/strings/string_view.h"
125 #include "absl/types/span.h"
129 #include "ortools/math_opt/model.pb.h"
130 #include "ortools/math_opt/model_update.pb.h"
131 #include "ortools/math_opt/result.pb.h"
132 #include "ortools/math_opt/solution.pb.h"
133 #include "ortools/math_opt/sparse_containers.pb.h"
152 inline const std::string&
name()
const {
return name_; }
169 bool is_integer, absl::string_view
name =
"");
174 inline const std::string&
variable_name(VariableId
id)
const;
204 std::vector<VariableId>
variables()
const;
228 absl::string_view
name =
"");
275 VariableId variable)
const;
277 LinearConstraintId constraint, VariableId variable)
const;
288 inline const absl::flat_hash_map<std::pair<LinearConstraintId, VariableId>,
297 LinearConstraintId constraint);
303 inline const absl::flat_hash_set<LinearConstraintId>&
315 VariableId variable)
const;
359 struct VariableData {
360 double lower_bound = -std::numeric_limits<double>::infinity();
361 double upper_bound = std::numeric_limits<double>::infinity();
362 bool is_integer =
false;
363 std::string
name =
"";
365 struct LinearConstraintData {
366 double lower_bound = -std::numeric_limits<double>::infinity();
367 double upper_bound = std::numeric_limits<double>::infinity();
368 std::string
name =
"";
371 template <
typename T>
372 void set_variable_property(VariableId
id, T
value, T VariableData::*field,
373 absl::flat_hash_set<VariableId>& dirty_set);
375 inline void set_linear_constraint_property(
376 const LinearConstraintId
id,
double value,
377 double LinearConstraintData::*field,
378 absl::flat_hash_set<LinearConstraintId>& dirty_set);
383 void EnsureLazyMatrixColumns();
388 void EnsureLazyMatrixRows();
391 void AppendVariable(VariableId
id, VariablesProto& variables_proto)
const;
394 void AppendLinearConstraint(
395 LinearConstraintId
id,
396 LinearConstraintsProto& linear_constraints_proto)
const;
401 void ExportLinearConstraintMatrix(
402 absl::Span<
const std::pair<LinearConstraintId, VariableId>> entries,
403 SparseDoubleMatrixProto& matrix)
const;
406 VariableId next_variable_id_ = VariableId(0);
407 LinearConstraintId next_linear_constraint_id_ = LinearConstraintId(0);
409 bool is_maximize_ =
false;
410 double objective_offset_ = 0.0;
412 absl::flat_hash_map<VariableId, VariableData> variables_;
413 absl::flat_hash_map<LinearConstraintId, LinearConstraintData>
416 absl::flat_hash_map<VariableId, double> linear_objective_;
418 absl::flat_hash_map<std::pair<LinearConstraintId, VariableId>,
double>
419 linear_constraint_matrix_;
420 absl::flat_hash_map<VariableId, absl::flat_hash_set<LinearConstraintId>>
421 lazy_matrix_columns_;
422 absl::flat_hash_map<LinearConstraintId, absl::flat_hash_set<VariableId>>
430 VariableId variables_checkpoint_ = VariableId(0);
431 LinearConstraintId linear_constraints_checkpoint_ = LinearConstraintId(0);
432 bool dirty_objective_direction_ =
false;
433 bool dirty_objective_offset_ =
false;
435 absl::flat_hash_set<VariableId> dirty_variable_deletes_;
436 absl::flat_hash_set<VariableId> dirty_variable_lower_bounds_;
437 absl::flat_hash_set<VariableId> dirty_variable_upper_bounds_;
438 absl::flat_hash_set<VariableId> dirty_variable_is_integer_;
440 absl::flat_hash_set<VariableId> dirty_linear_objective_coefficients_;
442 absl::flat_hash_set<LinearConstraintId> dirty_linear_constraint_deletes_;
443 absl::flat_hash_set<LinearConstraintId> dirty_linear_constraint_lower_bounds_;
444 absl::flat_hash_set<LinearConstraintId> dirty_linear_constraint_upper_bounds_;
450 absl::flat_hash_set<std::pair<LinearConstraintId, VariableId>>
451 dirty_linear_constraint_matrix_keys_;
540 const SolveResultProto& solve_result);
553 return AddVariable(-std::numeric_limits<double>::infinity(),
554 std::numeric_limits<double>::infinity(),
false,
name);
558 return variables_.at(
id).lower_bound;
562 return variables_.at(
id).upper_bound;
566 return variables_.at(
id).is_integer;
570 return variables_.at(
id).name;
573 template <
typename T>
574 void IndexedModel::set_variable_property(
575 const VariableId
id,
const T
value, T VariableData::*
const field,
576 absl::flat_hash_set<VariableId>& dirty_set) {
577 VariableData& var_data = variables_.at(
id);
578 if (var_data.*field !=
value) {
579 var_data.*field =
value;
580 if (
id < variables_checkpoint_) {
581 dirty_set.insert(
id);
589 dirty_variable_lower_bounds_);
595 dirty_variable_upper_bounds_);
599 const bool is_integer) {
600 set_variable_property(
id, is_integer, &VariableData::is_integer,
601 dirty_variable_is_integer_);
617 return variables_.contains(
id);
626 std::numeric_limits<double>::infinity(),
name);
630 const LinearConstraintId
id)
const {
631 return linear_constraints_.at(
id).lower_bound;
635 const LinearConstraintId
id)
const {
636 return linear_constraints_.at(
id).upper_bound;
640 const LinearConstraintId
id)
const {
641 return linear_constraints_.at(
id).name;
644 void IndexedModel::set_linear_constraint_property(
645 const LinearConstraintId
id,
const double value,
646 double LinearConstraintData::*
const field,
647 absl::flat_hash_set<LinearConstraintId>& dirty_set) {
648 LinearConstraintData& lin_con_data = linear_constraints_.at(
id);
649 if (lin_con_data.*field !=
value) {
650 lin_con_data.*field =
value;
651 if (
id < linear_constraints_checkpoint_) {
652 dirty_set.insert(
id);
658 const LinearConstraintId
id,
const double lower_bound) {
661 dirty_linear_constraint_lower_bounds_);
665 const LinearConstraintId
id,
const double upper_bound) {
668 dirty_linear_constraint_upper_bounds_);
672 return linear_constraints_.size();
676 return next_linear_constraint_id_;
680 return linear_constraints_.contains(
id);
688 LinearConstraintId constraint, VariableId variable)
const {
690 {constraint, variable});
694 LinearConstraintId constraint, VariableId variable)
const {
695 return linear_constraint_matrix_.contains({constraint, variable});
699 LinearConstraintId constraint, VariableId variable,
double value) {
700 bool was_updated =
false;
702 if (linear_constraint_matrix_.erase({constraint, variable}) > 0) {
704 if (!lazy_matrix_columns_.empty()) {
705 lazy_matrix_columns_.at(variable).erase(constraint);
707 if (!lazy_matrix_rows_.empty()) {
708 lazy_matrix_rows_.at(constraint).erase(variable);
712 const auto [iterator, inserted] =
713 linear_constraint_matrix_.try_emplace({constraint, variable},
value);
716 }
else if (iterator->second !=
value) {
717 iterator->second =
value;
720 if (!lazy_matrix_columns_.empty()) {
721 lazy_matrix_columns_.at(variable).insert(constraint);
723 if (!lazy_matrix_rows_.empty()) {
724 lazy_matrix_rows_.at(constraint).insert(variable);
727 if (was_updated && constraint < linear_constraints_checkpoint_ &&
728 variable < variables_checkpoint_) {
729 dirty_linear_constraint_matrix_keys_.emplace(constraint, variable);
733 const absl::flat_hash_map<std::pair<LinearConstraintId, VariableId>,
double>&
735 return linear_constraint_matrix_;
738 const absl::flat_hash_set<VariableId>&
740 EnsureLazyMatrixRows();
741 return lazy_matrix_rows_.at(constraint);
744 const absl::flat_hash_set<LinearConstraintId>&
746 EnsureLazyMatrixColumns();
747 return lazy_matrix_columns_.at(variable);
763 VariableId variable)
const {
764 return linear_objective_.contains(variable);
769 dirty_objective_direction_ =
true;
779 if (
value != objective_offset_) {
780 dirty_objective_offset_ =
true;
781 objective_offset_ =
value;
787 bool was_updated =
false;
789 if (linear_objective_.erase(variable) > 0) {
793 const auto [iterator, inserted] =
794 linear_objective_.try_emplace(variable,
value);
797 }
else if (iterator->second !=
value) {
798 iterator->second =
value;
802 if (was_updated && variable < variables_checkpoint_) {
803 dirty_linear_objective_coefficients_.insert(variable);
809 while (!linear_objective_.empty()) {
816 return linear_objective_;
IndexedModel(absl::string_view name="")
LinearConstraintId next_linear_constraint_id() const
std::vector< LinearConstraintId > linear_constraints() const
std::vector< VariableId > SortedVariables() const
void DeleteVariable(VariableId id)
void set_variable_as_continuous(VariableId id)
double linear_objective_coefficient(VariableId variable) const
int num_linear_constraints() const
std::vector< VariableId > SortedLinearObjectiveNonzeroVariables() const
double linear_constraint_coefficient(LinearConstraintId constraint, VariableId variable) const
void DeleteLinearConstraint(LinearConstraintId id)
void set_linear_objective_coefficient(VariableId variable, double value)
const absl::flat_hash_map< std::pair< LinearConstraintId, VariableId >, double > & linear_constraint_matrix() const
std::vector< VariableId > variables() const
int num_variables() const
double linear_constraint_lower_bound(LinearConstraintId id) const
double objective_offset() const
void set_linear_constraint_coefficient(LinearConstraintId constraint, VariableId variable, double value)
VariableId AddVariable(absl::string_view name="")
void set_variable_upper_bound(VariableId id, double upper_bound)
void set_variable_is_integer(VariableId id, bool is_integer)
bool has_linear_constraint(LinearConstraintId id) const
const std::string & variable_name(VariableId id) const
const absl::flat_hash_set< VariableId > & variables_in_linear_constraint(LinearConstraintId constraint)
void set_linear_constraint_upper_bound(LinearConstraintId id, double upper_bound)
ModelProto ExportModel() const
void set_is_maximize(bool is_maximize)
void set_linear_constraint_lower_bound(LinearConstraintId id, double lower_bound)
VariableId next_variable_id() const
double linear_constraint_upper_bound(LinearConstraintId id) const
void set_variable_as_integer(VariableId id)
bool has_variable(VariableId id) const
double variable_lower_bound(VariableId id) const
ModelUpdateProto ExportModelUpdate()
const std::string & name() const
const absl::flat_hash_set< LinearConstraintId > & linear_constraints_with_variable(VariableId variable)
bool is_linear_constraint_coefficient_nonzero(LinearConstraintId constraint, VariableId variable) const
bool is_variable_integer(VariableId id) const
const std::string & linear_constraint_name(LinearConstraintId id) const
LinearConstraintId AddLinearConstraint(absl::string_view name="")
const absl::flat_hash_map< VariableId, double > & linear_objective() const
std::vector< LinearConstraintId > SortedLinearConstraints() const
bool is_linear_objective_coefficient_nonzero(VariableId variable) const
double variable_upper_bound(VariableId id) const
void set_variable_lower_bound(VariableId id, double lower_bound)
void set_objective_offset(double value)
const Collection::value_type::second_type & FindWithDefault(const Collection &collection, const typename Collection::value_type::first_type &key, const typename Collection::value_type::second_type &value)
DEFINE_INT_TYPE(VariableId, int64_t)
IndexedSolutions IndexedSolutionsFromProto(const SolveResultProto &solve_result)
Collection of objects used to extend the Constraint Solver library.
absl::flat_hash_map< VariableId, BasisStatus > variable_status
absl::flat_hash_map< LinearConstraintId, BasisStatus > constraint_status
absl::flat_hash_map< VariableId, double > reduced_costs
absl::flat_hash_map< LinearConstraintId, double > dual_values
absl::flat_hash_map< VariableId, double > reduced_costs
absl::flat_hash_map< LinearConstraintId, double > dual_values
absl::flat_hash_map< VariableId, double > variable_values
absl::flat_hash_map< VariableId, double > variable_values
std::vector< IndexedDualSolution > dual_solutions
std::vector< IndexedPrimalSolution > primal_solutions
std::vector< IndexedPrimalRay > primal_rays
std::vector< IndexedBasis > basis
std::vector< IndexedDualRay > dual_rays