121 #ifndef OR_TOOLS_MATH_OPT_CORE_INDEXED_MODEL_H_ 122 #define OR_TOOLS_MATH_OPT_CORE_INDEXED_MODEL_H_ 133 #include "absl/base/thread_annotations.h" 134 #include "absl/container/flat_hash_map.h" 135 #include "absl/container/flat_hash_set.h" 136 #include "absl/meta/type_traits.h" 137 #include "absl/strings/string_view.h" 138 #include "absl/synchronization/mutex.h" 139 #include "absl/types/span.h" 142 #include "ortools/math_opt/model.pb.h" 143 #include "ortools/math_opt/model_update.pb.h" 144 #include "ortools/math_opt/result.pb.h" 145 #include "ortools/math_opt/solution.pb.h" 146 #include "ortools/math_opt/sparse_containers.pb.h" 214 ~UpdateTracker() ABSL_LOCKS_EXCLUDED(indexed_model_.update_trackers_lock_);
220 ABSL_LOCKS_EXCLUDED(indexed_model_.update_trackers_lock_);
224 void Checkpoint() ABSL_LOCKS_EXCLUDED(indexed_model_.update_trackers_lock_);
232 ABSL_LOCKS_EXCLUDED(indexed_model.update_trackers_lock_);
236 void CheckpointLocked()
237 ABSL_EXCLUSIVE_LOCKS_REQUIRED(indexed_model_.update_trackers_lock_);
245 std::vector<std::shared_ptr<const ModelUpdateProto>> updates_
246 ABSL_GUARDED_BY(indexed_model_.update_trackers_lock_);
256 inline const std::string&
name()
const {
return name_; }
273 bool is_integer, absl::string_view
name =
"");
278 inline const std::string&
variable_name(VariableId
id)
const;
308 std::vector<VariableId>
variables()
const;
332 absl::string_view
name =
"");
379 VariableId variable)
const;
381 LinearConstraintId constraint, VariableId variable)
const;
392 inline const absl::flat_hash_map<std::pair<LinearConstraintId, VariableId>,
401 LinearConstraintId constraint);
407 inline const absl::flat_hash_set<LinearConstraintId>&
419 VariableId variable)
const;
468 struct VariableData {
469 double lower_bound = -std::numeric_limits<double>::infinity();
470 double upper_bound = std::numeric_limits<double>::infinity();
471 bool is_integer =
false;
472 std::string
name =
"";
474 struct LinearConstraintData {
475 double lower_bound = -std::numeric_limits<double>::infinity();
476 double upper_bound = std::numeric_limits<double>::infinity();
477 std::string
name =
"";
480 template <
typename T>
481 void set_variable_property(VariableId
id, T
value, T VariableData::*field,
482 absl::flat_hash_set<VariableId>& dirty_set);
484 inline void set_linear_constraint_property(
485 const LinearConstraintId
id,
double value,
486 double LinearConstraintData::*field,
487 absl::flat_hash_set<LinearConstraintId>& dirty_set);
492 void EnsureLazyMatrixColumns();
497 void EnsureLazyMatrixRows();
500 void AppendVariable(VariableId
id, VariablesProto& variables_proto)
const;
503 void AppendLinearConstraint(
504 LinearConstraintId
id,
505 LinearConstraintsProto& linear_constraints_proto)
const;
510 void ExportLinearConstraintMatrix(
511 absl::Span<
const std::pair<LinearConstraintId, VariableId>> entries,
512 SparseDoubleMatrixProto& matrix)
const;
519 absl::optional<ModelUpdateProto> ExportSharedModelUpdate()
520 ABSL_EXCLUSIVE_LOCKS_REQUIRED(update_trackers_lock_);
524 void SharedCheckpoint() ABSL_EXCLUSIVE_LOCKS_REQUIRED(update_trackers_lock_);
527 VariableId next_variable_id_ = VariableId(0);
528 LinearConstraintId next_linear_constraint_id_ = LinearConstraintId(0);
530 bool is_maximize_ = false;
531 double objective_offset_ = 0.0;
533 absl::flat_hash_map<VariableId, VariableData> variables_;
534 absl::flat_hash_map<LinearConstraintId, LinearConstraintData>
537 absl::flat_hash_map<VariableId,
double> linear_objective_;
539 absl::flat_hash_map<std::pair<LinearConstraintId, VariableId>,
double>
540 linear_constraint_matrix_;
541 absl::flat_hash_map<VariableId,
absl::flat_hash_set<LinearConstraintId>>
542 lazy_matrix_columns_;
543 absl::flat_hash_map<LinearConstraintId,
absl::flat_hash_set<VariableId>>
551 VariableId variables_checkpoint_ = VariableId(0);
552 LinearConstraintId linear_constraints_checkpoint_ = LinearConstraintId(0);
553 bool dirty_objective_direction_ = false;
554 bool dirty_objective_offset_ = false;
556 absl::flat_hash_set<VariableId> dirty_variable_deletes_;
557 absl::flat_hash_set<VariableId> dirty_variable_lower_bounds_;
558 absl::flat_hash_set<VariableId> dirty_variable_upper_bounds_;
559 absl::flat_hash_set<VariableId> dirty_variable_is_integer_;
561 absl::flat_hash_set<VariableId> dirty_linear_objective_coefficients_;
563 absl::flat_hash_set<LinearConstraintId> dirty_linear_constraint_deletes_;
564 absl::flat_hash_set<LinearConstraintId> dirty_linear_constraint_lower_bounds_;
565 absl::flat_hash_set<LinearConstraintId> dirty_linear_constraint_upper_bounds_;
571 absl::flat_hash_set<std::pair<LinearConstraintId, VariableId>>
572 dirty_linear_constraint_matrix_keys_;
578 absl::Mutex update_trackers_lock_;
583 absl::flat_hash_set<UpdateTracker*> update_trackers_
584 ABSL_GUARDED_BY(update_trackers_lock_);
673 const SolveResultProto& solve_result);
686 return AddVariable(-std::numeric_limits<double>::infinity(),
687 std::numeric_limits<double>::infinity(),
false,
name);
691 return variables_.at(
id).lower_bound;
695 return variables_.at(
id).upper_bound;
699 return variables_.at(
id).is_integer;
703 return variables_.at(
id).name;
706 template <
typename T>
707 void IndexedModel::set_variable_property(
708 const VariableId
id,
const T
value, T VariableData::*
const field,
709 absl::flat_hash_set<VariableId>& dirty_set) {
710 VariableData& var_data = variables_.at(
id);
711 if (var_data.*field !=
value) {
712 var_data.*field =
value;
713 if (
id < variables_checkpoint_) {
714 dirty_set.insert(
id);
722 dirty_variable_lower_bounds_);
728 dirty_variable_upper_bounds_);
732 const bool is_integer) {
733 set_variable_property(
id, is_integer, &VariableData::is_integer,
734 dirty_variable_is_integer_);
750 return variables_.contains(
id);
759 std::numeric_limits<double>::infinity(),
name);
763 const LinearConstraintId
id)
const {
764 return linear_constraints_.at(
id).lower_bound;
768 const LinearConstraintId
id)
const {
769 return linear_constraints_.at(
id).upper_bound;
773 const LinearConstraintId
id)
const {
774 return linear_constraints_.at(
id).name;
777 void IndexedModel::set_linear_constraint_property(
778 const LinearConstraintId
id,
const double value,
779 double LinearConstraintData::*
const field,
780 absl::flat_hash_set<LinearConstraintId>& dirty_set) {
781 LinearConstraintData& lin_con_data = linear_constraints_.at(
id);
782 if (lin_con_data.*field !=
value) {
783 lin_con_data.*field =
value;
784 if (
id < linear_constraints_checkpoint_) {
785 dirty_set.insert(
id);
791 const LinearConstraintId
id,
const double lower_bound) {
794 dirty_linear_constraint_lower_bounds_);
798 const LinearConstraintId
id,
const double upper_bound) {
801 dirty_linear_constraint_upper_bounds_);
805 return linear_constraints_.size();
809 return next_linear_constraint_id_;
813 return linear_constraints_.contains(
id);
821 LinearConstraintId constraint, VariableId variable)
const {
823 {constraint, variable});
827 LinearConstraintId constraint, VariableId variable)
const {
828 return linear_constraint_matrix_.contains({constraint, variable});
832 LinearConstraintId constraint, VariableId variable,
double value) {
833 bool was_updated =
false;
835 if (linear_constraint_matrix_.erase({constraint, variable}) > 0) {
837 if (!lazy_matrix_columns_.empty()) {
838 lazy_matrix_columns_.at(variable).erase(constraint);
840 if (!lazy_matrix_rows_.empty()) {
841 lazy_matrix_rows_.at(constraint).erase(variable);
845 const auto [iterator, inserted] =
846 linear_constraint_matrix_.try_emplace({constraint, variable},
value);
849 }
else if (iterator->second !=
value) {
850 iterator->second =
value;
853 if (!lazy_matrix_columns_.empty()) {
854 lazy_matrix_columns_.at(variable).insert(constraint);
856 if (!lazy_matrix_rows_.empty()) {
857 lazy_matrix_rows_.at(constraint).insert(variable);
860 if (was_updated && constraint < linear_constraints_checkpoint_ &&
861 variable < variables_checkpoint_) {
862 dirty_linear_constraint_matrix_keys_.emplace(constraint, variable);
866 const absl::flat_hash_map<std::pair<LinearConstraintId, VariableId>,
double>&
868 return linear_constraint_matrix_;
871 const absl::flat_hash_set<VariableId>&
873 EnsureLazyMatrixRows();
874 return lazy_matrix_rows_.at(constraint);
877 const absl::flat_hash_set<LinearConstraintId>&
879 EnsureLazyMatrixColumns();
880 return lazy_matrix_columns_.at(variable);
896 VariableId variable)
const {
897 return linear_objective_.contains(variable);
902 dirty_objective_direction_ =
true;
912 if (
value != objective_offset_) {
913 dirty_objective_offset_ =
true;
914 objective_offset_ =
value;
920 bool was_updated =
false;
922 if (linear_objective_.erase(variable) > 0) {
926 const auto [iterator, inserted] =
927 linear_objective_.try_emplace(variable,
value);
930 }
else if (iterator->second !=
value) {
931 iterator->second =
value;
935 if (was_updated && variable < variables_checkpoint_) {
936 dirty_linear_objective_coefficients_.insert(variable);
942 while (!linear_objective_.empty()) {
949 return linear_objective_;
955 #endif // OR_TOOLS_MATH_OPT_CORE_INDEXED_MODEL_H_ std::vector< IndexedPrimalSolution > primal_solutions
const std::string & variable_name(VariableId id) const
std::vector< VariableId > variables() const
LinearConstraintId AddLinearConstraint(absl::string_view name="")
void set_linear_constraint_lower_bound(LinearConstraintId id, double lower_bound)
LinearConstraintId next_linear_constraint_id() const
void set_linear_objective_coefficient(VariableId variable, double value)
~UpdateTracker() ABSL_LOCKS_EXCLUDED(indexed_model_.update_trackers_lock_)
absl::flat_hash_map< VariableId, BasisStatus > variable_status
absl::flat_hash_map< VariableId, double > reduced_costs
void set_linear_constraint_coefficient(LinearConstraintId constraint, VariableId variable, double value)
const absl::flat_hash_map< std::pair< LinearConstraintId, VariableId >, double > & linear_constraint_matrix() const
VariableId AddVariable(absl::string_view name="")
std::vector< IndexedDualRay > dual_rays
absl::flat_hash_map< VariableId, double > reduced_costs
absl::flat_hash_map< VariableId, double > variable_values
bool has_linear_constraint(LinearConstraintId id) const
double objective_offset() const
std::vector< IndexedDualSolution > dual_solutions
int num_linear_constraints() const
double linear_constraint_lower_bound(LinearConstraintId id) const
void set_objective_offset(double value)
DEFINE_INT_TYPE(VariableId, int64_t)
void set_variable_lower_bound(VariableId id, double lower_bound)
void set_variable_as_integer(VariableId id)
const absl::flat_hash_map< VariableId, double > & linear_objective() const
std::vector< LinearConstraintId > SortedLinearConstraints() const
std::unique_ptr< UpdateTracker > NewUpdateTracker()
double linear_constraint_coefficient(LinearConstraintId constraint, VariableId variable) const
const absl::flat_hash_set< LinearConstraintId > & linear_constraints_with_variable(VariableId variable)
void set_linear_constraint_upper_bound(LinearConstraintId id, double upper_bound)
IndexedModel & operator=(const IndexedModel &)=delete
absl::optional< ModelUpdateProto > ExportModelUpdate() ABSL_LOCKS_EXCLUDED(indexed_model_.update_trackers_lock_)
VariableId next_variable_id() const
absl::flat_hash_map< LinearConstraintId, double > dual_values
std::vector< VariableId > SortedVariables() const
bool has_variable(VariableId id) const
const std::string & name() const
friend class IndexedModel
absl::flat_hash_map< LinearConstraintId, BasisStatus > constraint_status
double variable_lower_bound(VariableId id) const
bool is_linear_objective_coefficient_nonzero(VariableId variable) const
void Checkpoint() ABSL_LOCKS_EXCLUDED(indexed_model_.update_trackers_lock_)
void DeleteLinearConstraint(LinearConstraintId id)
IndexedSolutions IndexedSolutionsFromProto(const SolveResultProto &solve_result)
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)
bool is_variable_integer(VariableId id) const
int num_variables() const
double linear_constraint_upper_bound(LinearConstraintId id) const
void set_is_maximize(bool is_maximize)
void set_variable_is_integer(VariableId id, bool is_integer)
absl::flat_hash_map< LinearConstraintId, double > dual_values
const absl::flat_hash_set< VariableId > & variables_in_linear_constraint(LinearConstraintId constraint)
void set_variable_upper_bound(VariableId id, double upper_bound)
std::vector< LinearConstraintId > linear_constraints() const
absl::flat_hash_map< VariableId, double > variable_values
Collection of objects used to extend the Constraint Solver library.
std::vector< IndexedBasis > basis
void set_variable_as_continuous(VariableId id)
std::vector< VariableId > SortedLinearObjectiveNonzeroVariables() const
std::vector< IndexedPrimalRay > primal_rays
const std::string & linear_constraint_name(LinearConstraintId id) const
bool is_linear_constraint_coefficient_nonzero(LinearConstraintId constraint, VariableId variable) const
double linear_objective_coefficient(VariableId variable) const
void DeleteVariable(VariableId id)
double variable_upper_bound(VariableId id) const
ModelProto ExportModel() const