diff --git a/examples/cpp/fap_parser.cc b/examples/cpp/fap_parser.cc index 74ce7121aa..054013c1b4 100644 --- a/examples/cpp/fap_parser.cc +++ b/examples/cpp/fap_parser.cc @@ -52,7 +52,7 @@ void VariableParser::Parse() { variable.initial_position = atoi32(tokens[2].c_str()); variable.mobility_index = atoi32(tokens[3].c_str()); } - InsertOrUpdate(&variables_, atoi32(tokens[0].c_str()), variable); + gtl::InsertOrUpdate(&variables_, atoi32(tokens[0].c_str()), variable); } } @@ -81,7 +81,7 @@ void DomainParser::Parse() { } if (!domain.empty()) { - InsertOrUpdate(&domains_, key, domain); + gtl::InsertOrUpdate(&domains_, key, domain); } } } @@ -193,8 +193,8 @@ void FindComponents(const std::vector& constraints, for (const FapConstraint& constraint : constraints) { const int variable_id1 = constraint.variable1; const int variable_id2 = constraint.variable2; - const FapVariable& variable1 = FindOrDie(variables, variable_id1); - const FapVariable& variable2 = FindOrDie(variables, variable_id2); + const FapVariable& variable1 = gtl::FindOrDie(variables, variable_id1); + const FapVariable& variable2 = gtl::FindOrDie(variables, variable_id2); CHECK_LT(variable_id1, in_component.size()); CHECK_LT(variable_id2, in_component.size()); if (in_component[variable_id1] < 0 && in_component[variable_id2] < 0) { @@ -202,19 +202,19 @@ void FindComponents(const std::vector& constraints, // Create a new one. FapComponent component; const int component_index = constraint_index; - InsertOrUpdate(&(component.variables), variable_id1, variable1); - InsertOrUpdate(&(component.variables), variable_id2, variable2); + gtl::InsertOrUpdate(&(component.variables), variable_id1, variable1); + gtl::InsertOrUpdate(&(component.variables), variable_id2, variable2); in_component[variable_id1] = component_index; in_component[variable_id2] = component_index; component.constraints.push_back(constraint); - InsertOrUpdate(components, component_index, component); + gtl::InsertOrUpdate(components, component_index, component); } else if (in_component[variable_id1] >= 0 && in_component[variable_id2] < 0) { // If variable1 belongs to an existing component, variable2 should // also be included in the same component. const int component_index = in_component[variable_id1]; - CHECK(ContainsKey(*components, component_index)); - InsertOrUpdate(&((*components)[component_index].variables), variable_id2, + CHECK(gtl::ContainsKey(*components, component_index)); + gtl::InsertOrUpdate(&((*components)[component_index].variables), variable_id2, variable2); in_component[variable_id2] = component_index; (*components)[component_index].constraints.push_back(constraint); @@ -223,8 +223,8 @@ void FindComponents(const std::vector& constraints, // If variable2 belongs to an existing component, variable1 should // also be included in the same component. const int component_index = in_component[variable_id2]; - CHECK(ContainsKey(*components, component_index)); - InsertOrUpdate(&((*components)[component_index].variables), variable_id1, + CHECK(gtl::ContainsKey(*components, component_index)); + gtl::InsertOrUpdate(&((*components)[component_index].variables), variable_id1, variable1); in_component[variable_id1] = component_index; (*components)[component_index].constraints.push_back(constraint); @@ -236,8 +236,8 @@ void FindComponents(const std::vector& constraints, std::min(component_index1, component_index2); const int max_component_index = std::max(component_index1, component_index2); - CHECK(ContainsKey(*components, min_component_index)); - CHECK(ContainsKey(*components, max_component_index)); + CHECK(gtl::ContainsKey(*components, min_component_index)); + CHECK(gtl::ContainsKey(*components, max_component_index)); if (min_component_index != max_component_index) { // Update the component_index of maximum indexed component's variables. for (const auto& variable : @@ -272,8 +272,8 @@ void FindComponents(const std::vector& constraints, int EvaluateConstraintImpact(const std::map& variables, const int max_weight_cost, const FapConstraint constraint) { - const FapVariable& variable1 = FindOrDie(variables, constraint.variable1); - const FapVariable& variable2 = FindOrDie(variables, constraint.variable2); + const FapVariable& variable1 = gtl::FindOrDie(variables, constraint.variable1); + const FapVariable& variable2 = gtl::FindOrDie(variables, constraint.variable2); const int degree1 = variable1.degree; const int degree2 = variable2.degree; const int max_degree = std::max(degree1, degree2); @@ -321,7 +321,7 @@ void ParseInstance(const std::string& data_directory, bool find_components, // Make the variables of the instance. for (auto& it : *variables) { - it.second.domain = FindOrDie(dom.domains(), it.second.domain_index); + it.second.domain = gtl::FindOrDie(dom.domains(), it.second.domain_index); it.second.domain_size = it.second.domain.size(); if ((it.second.mobility_index == -1) || (it.second.mobility_index == 0)) { @@ -347,7 +347,7 @@ void ParseInstance(const std::string& data_directory, bool find_components, ++((*variables)[ct.variable2]).degree; } // Make the available frequencies of the instance. - *frequencies = FindOrDie(dom.domains(), 0); + *frequencies = gtl::FindOrDie(dom.domains(), 0); // Make the objective of the instance. *objective = cst.objective(); diff --git a/examples/cpp/fap_utilities.cc b/examples/cpp/fap_utilities.cc index 2857c30288..4c492f2ae8 100644 --- a/examples/cpp/fap_utilities.cc +++ b/examples/cpp/fap_utilities.cc @@ -31,8 +31,8 @@ bool CheckConstraintSatisfaction( const std::map& index_from_key) { bool status = true; for (const FapConstraint& ct : data_constraints) { - const int index1 = FindOrDie(index_from_key, ct.variable1); - const int index2 = FindOrDie(index_from_key, ct.variable2); + const int index1 = gtl::FindOrDie(index_from_key, ct.variable1); + const int index2 = gtl::FindOrDie(index_from_key, ct.variable2); CHECK_LT(index1, variables.size()); CHECK_LT(index2, variables.size()); const int var1 = variables[index1]; @@ -63,7 +63,7 @@ bool CheckVariablePosition(const std::map& data_variables, const std::map& index_from_key) { bool status = true; for (const auto& it : data_variables) { - const int index = FindOrDie(index_from_key, it.first); + const int index = gtl::FindOrDie(index_from_key, it.first); CHECK_LT(index, variables.size()); const int var = variables[index]; diff --git a/examples/cpp/frequency_assignment_problem.cc b/examples/cpp/frequency_assignment_problem.cc index 379c652750..a953a6af35 100644 --- a/examples/cpp/frequency_assignment_problem.cc +++ b/examples/cpp/frequency_assignment_problem.cc @@ -194,8 +194,8 @@ class OrderingBuilder : public DecisionBuilder { Decision* Next(Solver* const s) override { if (iter_ < size_) { FapConstraint constraint = data_constraints_[iter_]; - const int index1 = FindOrDie(index_from_key_, constraint.variable1); - const int index2 = FindOrDie(index_from_key_, constraint.variable2); + const int index1 = gtl::FindOrDie(index_from_key_, constraint.variable1); + const int index2 = gtl::FindOrDie(index_from_key_, constraint.variable2); IntVar* variable1 = variables_[index1]; IntVar* variable2 = variables_[index2]; @@ -272,8 +272,8 @@ class OrderingBuilder : public DecisionBuilder { Order Hint(const FapConstraint& constraint) { const int id1 = constraint.variable1; const int id2 = constraint.variable2; - const int variable1 = FindOrDie(index_from_key_, id1); - const int variable2 = FindOrDie(index_from_key_, id2); + const int variable1 = gtl::FindOrDie(index_from_key_, id1); + const int variable2 = gtl::FindOrDie(index_from_key_, id2); const int value = constraint.value; CHECK_LT(variable1, variable_state_.size()); CHECK_LT(variable2, variable_state_.size()); @@ -361,7 +361,7 @@ int64 ValueEvaluator( } std::pair new_value_ranking = std::make_pair(new_value, new_ranking); - InsertOrUpdate(value_evaluator_map, variable_index, new_value_ranking); + gtl::InsertOrUpdate(value_evaluator_map, variable_index, new_value_ranking); return new_ranking; } @@ -372,7 +372,7 @@ int64 VariableEvaluator(const std::vector& key_from_index, const std::map& data_variables, int64 variable_index) { FapVariable variable = - FindOrDie(data_variables, key_from_index[variable_index]); + gtl::FindOrDie(data_variables, key_from_index[variable_index]); int64 result = -(variable.degree * 100 / variable.domain_size); return result; } @@ -395,7 +395,7 @@ void CreateModelVariables(const std::map& data_variables, for (const auto& it : data_variables) { CHECK_LT(index, model_variables->size()); (*model_variables)[index] = solver->MakeIntVar(it.second.domain); - InsertOrUpdate(index_from_key, it.first, index); + gtl::InsertOrUpdate(index_from_key, it.first, index); (*key_from_index)[index] = it.first; if ((it.second.initial_position != -1) && (it.second.hard)) { @@ -415,8 +415,8 @@ void CreateModelConstraints(const std::vector& data_constraints, CHECK_NOTNULL(solver); for (const FapConstraint& ct : data_constraints) { - const int index1 = FindOrDie(index_from_key, ct.variable1); - const int index2 = FindOrDie(index_from_key, ct.variable2); + const int index1 = gtl::FindOrDie(index_from_key, ct.variable1); + const int index2 = gtl::FindOrDie(index_from_key, ct.variable2); CHECK_LT(index1, variables.size()); CHECK_LT(index2, variables.size()); IntVar* var1 = variables[index1]; @@ -630,10 +630,10 @@ void SplitVariablesHardSoft(const std::map& data_variables, if (it.second.initial_position != -1) { if (it.second.hard) { CHECK_LT(it.second.mobility_cost, 0); - InsertOrUpdate(hard_variables, it.first, it.second); + gtl::InsertOrUpdate(hard_variables, it.first, it.second); } else { CHECK_GE(it.second.mobility_cost, 0); - InsertOrUpdate(soft_variables, it.first, it.second); + gtl::InsertOrUpdate(soft_variables, it.first, it.second); } } } @@ -662,7 +662,7 @@ void PenalizeVariablesViolation( const std::vector& variables, std::vector* cost, Solver* solver) { for (const auto& it : soft_variables) { - const int index = FindOrDie(index_from_key, it.first); + const int index = gtl::FindOrDie(index_from_key, it.first); CHECK_LT(index, variables.size()); IntVar* const displaced = solver->MakeIsDifferentCstVar( variables[index], it.second.initial_position); @@ -692,8 +692,8 @@ void PenalizeConstraintsViolation( } for (const FapConstraint& ct : soft_constraints) { - const int index1 = FindOrDie(index_from_key, ct.variable1); - const int index2 = FindOrDie(index_from_key, ct.variable2); + const int index1 = gtl::FindOrDie(index_from_key, ct.variable1); + const int index2 = gtl::FindOrDie(index_from_key, ct.variable2); CHECK_LT(index1, variables.size()); CHECK_LT(index2, variables.size()); IntVar* const absolute_difference = diff --git a/examples/cpp/network_routing.cc b/examples/cpp/network_routing.cc index c8c0a83419..5a4dc9c787 100644 --- a/examples/cpp/network_routing.cc +++ b/examples/cpp/network_routing.cc @@ -117,7 +117,7 @@ class NetworkRoutingData { // Returns the capacity of an arc, and 0 if the arc is not defined. int Capacity(int node1, int node2) const { - return FindWithDefault( + return gtl::FindWithDefault( all_arcs_, std::make_pair(std::min(node1, node2), std::max(node1, node2)), 0); } @@ -125,8 +125,8 @@ class NetworkRoutingData { // Returns the demand between the source and the destination, and 0 if // there are no demands between the source and the destination. int Demand(int source, int destination) const { - return FindWithDefault(all_demands_, std::make_pair(source, destination), - 0); + return gtl::FindWithDefault(all_demands_, + std::make_pair(source, destination), 0); } // External building API. @@ -636,7 +636,7 @@ class NetworkRoutingSolver { for (int i = 0; i < demands; ++i) { const OnePath& path = all_paths_[i][Value(i)]; for (const int arc : arcs_to_release) { - if (ContainsKey(path, arc)) { + if (gtl::ContainsKey(path, arc)) { AppendToFragment(i); break; } diff --git a/examples/cpp/nqueens.cc b/examples/cpp/nqueens.cc index 3e38c41771..c2100cf1dd 100644 --- a/examples/cpp/nqueens.cc +++ b/examples/cpp/nqueens.cc @@ -61,7 +61,7 @@ class NQueenSymmetry : public SymmetryBreaker { protected: int Index(IntVar* const var) const { - return FindWithDefault(indices_, var, -1); + return gtl::FindWithDefault(indices_, var, -1); } IntVar* Var(int index) const { DCHECK_GE(index, 0); diff --git a/examples/cpp/shift_minimization_sat.cc b/examples/cpp/shift_minimization_sat.cc index 00f90ba20e..8d0b30e47d 100644 --- a/examples/cpp/shift_minimization_sat.cc +++ b/examples/cpp/shift_minimization_sat.cc @@ -259,7 +259,7 @@ void LoadAndSolve(const std::string& file_name) { } // Check that we have not already visited this exact set of candidate jobs. - if (ContainsKey(visited_job_lists, intersecting_jobs)) continue; + if (gtl::ContainsKey(visited_job_lists, intersecting_jobs)) continue; visited_job_lists.insert(intersecting_jobs); // Collect the relevant literals, and regroup them per worker. @@ -275,7 +275,7 @@ void LoadAndSolve(const std::string& file_name) { std::vector active_worker_literals; for (const auto& it : active_literals_per_workers) { Literal active; - if (ContainsKey(active_literal_cache, it.second)) { + if (gtl::ContainsKey(active_literal_cache, it.second)) { active = active_literal_cache[it.second]; num_reused_literals++; } else { diff --git a/examples/cpp/weighted_tardiness_sat.cc b/examples/cpp/weighted_tardiness_sat.cc index ed8cff77e0..4d4cb9f1d4 100644 --- a/examples/cpp/weighted_tardiness_sat.cc +++ b/examples/cpp/weighted_tardiness_sat.cc @@ -258,7 +258,7 @@ void ParseAndSolve() { entries = absl::StrSplit(line, ' ', absl::SkipEmpty()); for (const std::string& entry : entries) { numbers.push_back(0); - safe_strto32(entry, &numbers.back()); + strings::safe_strto32(entry, &numbers.back()); } } diff --git a/ortools/algorithms/hungarian.h b/ortools/algorithms/hungarian.h index 91d72b7838..a124bf3bef 100644 --- a/ortools/algorithms/hungarian.h +++ b/ortools/algorithms/hungarian.h @@ -51,7 +51,6 @@ void MaximizeLinearAssignment( const std::vector >& cost, std::unordered_map* direct_assignment, std::unordered_map* reverse_assignment); - } // namespace operations_research #endif // OR_TOOLS_ALGORITHMS_HUNGARIAN_H_ diff --git a/ortools/algorithms/knapsack_solver.cc b/ortools/algorithms/knapsack_solver.cc index 53d9596f71..a9059d97b9 100644 --- a/ortools/algorithms/knapsack_solver.cc +++ b/ortools/algorithms/knapsack_solver.cc @@ -166,7 +166,7 @@ KnapsackPropagator::KnapsackPropagator(const KnapsackState& state) profit_upper_bound_(kint64max), state_(state) {} -KnapsackPropagator::~KnapsackPropagator() { STLDeleteElements(&items_); } +KnapsackPropagator::~KnapsackPropagator() { gtl::STLDeleteElements(&items_); } void KnapsackPropagator::Init(const std::vector& profits, const std::vector& weights) { @@ -441,8 +441,8 @@ int64 KnapsackGenericSolver::Solve(TimeLimit* time_limit, } void KnapsackGenericSolver::Clear() { - STLDeleteElements(&propagators_); - STLDeleteElements(&search_nodes_); + gtl::STLDeleteElements(&propagators_); + gtl::STLDeleteElements(&search_nodes_); } // Returns false when at least one propagator fails. diff --git a/ortools/base/map_util.h b/ortools/base/map_util.h index 259b2610e3..dfe9f67fc4 100644 --- a/ortools/base/map_util.h +++ b/ortools/base/map_util.h @@ -17,6 +17,7 @@ #include #include "ortools/base/logging.h" +namespace gtl { // Perform a lookup in a map or std::unordered_map. // If the key is present in the map then the value associated with that // key is returned, otherwise the value passed as a default is returned. @@ -190,5 +191,5 @@ typename Collection::value_type::second_type& LookupOrInsert( collection->insert(typename Collection::value_type(key, value)); return ret.first->second; } - +} // namespace gtl #endif // OR_TOOLS_BASE_MAP_UTIL_H_ diff --git a/ortools/base/mutex.cc b/ortools/base/mutex.cc index 06ce71dc58..6ce77e3209 100644 --- a/ortools/base/mutex.cc +++ b/ortools/base/mutex.cc @@ -15,7 +15,7 @@ #include "ortools/base/mutex.h" -namespace operations_research { +namespace absl { Mutex::Mutex() {} Mutex::~Mutex() {} void Mutex::Lock() { real_mutex_.lock(); } @@ -30,4 +30,4 @@ void CondVar::Wait(Mutex* const mu) { } void CondVar::Signal() { real_condition_.notify_one(); } void CondVar::SignalAll() { real_condition_.notify_all(); } -} // namespace operations_research +} // namespace absl diff --git a/ortools/base/mutex.h b/ortools/base/mutex.h index d0d3a6d2e9..1a10433cbb 100644 --- a/ortools/base/mutex.h +++ b/ortools/base/mutex.h @@ -19,7 +19,7 @@ #include "ortools/base/macros.h" -namespace operations_research { +namespace absl { class Mutex { public: Mutex(); @@ -68,5 +68,5 @@ class CondVar { #define EXCLUSIVE_LOCKS_REQUIRED(x) #define NO_THREAD_SAFETY_ANALYSIS #define GUARDED_BY(x) -} // namespace operations_research +} // namespace absl #endif // OR_TOOLS_BASE_MUTEX_H_ diff --git a/ortools/base/numbers.cc b/ortools/base/numbers.cc index 4e514b271a..66adc14e00 100644 --- a/ortools/base/numbers.cc +++ b/ortools/base/numbers.cc @@ -21,6 +21,8 @@ #define strtoll _strtoi64 #endif // _MSC_VER +namespace strings { + bool safe_strtof(const char* str, float* value) { char* endptr; *value = strtof(str, &endptr); @@ -67,5 +69,7 @@ bool safe_strto32(const std::string& str, int* value) { *value = strtol(str.c_str(), &endptr, /*base=*/10); // NOLINT return *endptr == '\0' && str[0] != '\0'; } + +} // namespace strings #undef strtof #undef strtoll diff --git a/ortools/base/numbers.h b/ortools/base/numbers.h index 2d6b033864..daf9a0a8b2 100644 --- a/ortools/base/numbers.h +++ b/ortools/base/numbers.h @@ -18,6 +18,8 @@ #include "ortools/base/integral_types.h" #include "ortools/base/join.h" +namespace strings { + // Convert strings to numerical values. // Leading and trailing spaces are allowed. // Values may be rounded on over- and underflow. @@ -30,4 +32,6 @@ bool safe_strto32(const std::string& str, int* value); // Converting int to std::string. inline std::string SimpleItoa(int i) { return StrCat(i); } +} // namespace strings + #endif // OR_TOOLS_BASE_NUMBERS_H_ diff --git a/ortools/base/stl_util.h b/ortools/base/stl_util.h index f994cde4e6..a723f869a1 100644 --- a/ortools/base/stl_util.h +++ b/ortools/base/stl_util.h @@ -17,7 +17,7 @@ #include #include -namespace operations_research { +namespace gtl { // STLDeleteContainerPointers() // For a range within a container of pointers, calls delete @@ -116,5 +116,5 @@ inline void STLSortAndRemoveDuplicates(T* v) { v->erase(std::unique(v->begin(), v->end()), v->end()); } -} // namespace operations_research +} // namespace gtl #endif // OR_TOOLS_BASE_STL_UTIL_H_ diff --git a/ortools/base/typeid.h b/ortools/base/typeid.h index f4780a337f..876ab7b7d5 100644 --- a/ortools/base/typeid.h +++ b/ortools/base/typeid.h @@ -14,11 +14,11 @@ #ifndef OR_TOOLS_BASE_TYPEID_H_ #define OR_TOOLS_BASE_TYPEID_H_ -namespace operations_research { +namespace gtl { template inline size_t FastTypeId() { static char d; return reinterpret_cast(&d); } -} // namespace operations_research +} // namespace gtl #endif // OR_TOOLS_BASE_TYPEID_H_ diff --git a/ortools/bop/bop_base.cc b/ortools/bop/bop_base.cc index c9919bcefe..93c0f4b2f5 100644 --- a/ortools/bop/bop_base.cc +++ b/ortools/bop/bop_base.cc @@ -17,6 +17,7 @@ #include #include +#include "ortools/base/mutex.h" #include "ortools/sat/boolean_problem.h" namespace operations_research { diff --git a/ortools/bop/bop_base.h b/ortools/bop/bop_base.h index 4a71ddca68..95cb1b513d 100644 --- a/ortools/bop/bop_base.h +++ b/ortools/bop/bop_base.h @@ -17,6 +17,7 @@ #include #include "ortools/base/basictypes.h" +#include "ortools/base/mutex.h" #include "ortools/bop/bop_parameters.pb.h" #include "ortools/bop/bop_solution.h" #include "ortools/lp_data/lp_types.h" diff --git a/ortools/bop/bop_ls.h b/ortools/bop/bop_ls.h index 3c226ebba5..a0ea35ae17 100644 --- a/ortools/bop/bop_ls.h +++ b/ortools/bop/bop_ls.h @@ -612,7 +612,8 @@ class LocalSearchAssignmentIterator { // Ideally, this should be related to the maximum number of decision in the // LS, but that requires templating the whole LS optimizer. bool use_transposition_table_; - std::unordered_set> transposition_table_; + std::unordered_set> + transposition_table_; bool use_potential_one_flip_repairs_; diff --git a/ortools/bop/bop_portfolio.cc b/ortools/bop/bop_portfolio.cc index 91f8e5b74a..bd3954c101 100644 --- a/ortools/bop/bop_portfolio.cc +++ b/ortools/bop/bop_portfolio.cc @@ -83,7 +83,7 @@ PortfolioOptimizer::~PortfolioOptimizer() { // Note that unique pointers are not used due to unsupported emplace_back // in ITIVectors. - STLDeleteElements(&optimizers_); + gtl::STLDeleteElements(&optimizers_); } BopOptimizerBase::Status PortfolioOptimizer::SynchronizeIfNeeded( diff --git a/ortools/constraint_solver/ac4_mdd_reset_table.cc b/ortools/constraint_solver/ac4_mdd_reset_table.cc index bc14a3fef0..077579bdca 100644 --- a/ortools/constraint_solver/ac4_mdd_reset_table.cc +++ b/ortools/constraint_solver/ac4_mdd_reset_table.cc @@ -95,7 +95,7 @@ class MddFactory { public: VmRec(Mdd* value = nullptr) : mdd_(), vmr_(), value_(value) {} - ~VmRec() { STLDeleteElements(&vmr_); } + ~VmRec() { gtl::STLDeleteElements(&vmr_); } VmRec* next(Mdd* mdd) { if (mdd == nullptr) { @@ -139,7 +139,7 @@ class MddFactory { std::vector > vm_; MddFactory() : nb_instance(1) {} - ~MddFactory() { STLDeleteElements(&g_); } + ~MddFactory() { gtl::STLDeleteElements(&g_); } int getNbInstance() { return nb_instance; } @@ -1042,7 +1042,7 @@ class MddTableVar { } } - ~MddTableVar() { STLDeleteElements(&edges_per_value_); } + ~MddTableVar() { gtl::STLDeleteElements(&edges_per_value_); } IntVar* Variable() const { return var_; } @@ -1297,7 +1297,7 @@ class Ac4MddTableConstraint : public Constraint { } ~Ac4MddTableConstraint() { - STLDeleteElements(&vars_); // delete all elements of a vector + gtl::STLDeleteElements(&vars_); // delete all elements of a vector delete shared_positions_edges_; } diff --git a/ortools/constraint_solver/ac4r_table.cc b/ortools/constraint_solver/ac4r_table.cc index fbf3e6c002..95f3d4a958 100644 --- a/ortools/constraint_solver/ac4r_table.cc +++ b/ortools/constraint_solver/ac4r_table.cc @@ -128,7 +128,8 @@ class TableVar { } ~TableVar() { - STLDeleteElements(&tuples_per_value_); // delete all elements of a vector + // delete all elements of a vector + gtl::STLDeleteElements(&tuples_per_value_); } IntVar* Variable() const { return var_; } @@ -321,7 +322,7 @@ class Ac4TableConstraint : public Constraint { } ~Ac4TableConstraint() { - STLDeleteElements(&vars_); // delete all elements of a vector + gtl::STLDeleteElements(&vars_); // delete all elements of a vector if (delete_table_) { delete table_; } diff --git a/ortools/constraint_solver/assignment.cc b/ortools/constraint_solver/assignment.cc index 7d14a84918..234f6581fa 100644 --- a/ortools/constraint_solver/assignment.cc +++ b/ortools/constraint_solver/assignment.cc @@ -383,19 +383,19 @@ void SequenceVarElement::SetUnperformed(const std::vector& unperformed) { bool SequenceVarElement::CheckClassInvariants() { std::unordered_set visited; for (const int forward_sequence : forward_sequence_) { - if (ContainsKey(visited, forward_sequence)) { + if (gtl::ContainsKey(visited, forward_sequence)) { return false; } visited.insert(forward_sequence); } for (const int backward_sequence : backward_sequence_) { - if (ContainsKey(visited, backward_sequence)) { + if (gtl::ContainsKey(visited, backward_sequence)) { return false; } visited.insert(backward_sequence); } for (const int unperformed : unperformed_) { - if (ContainsKey(visited, unperformed)) { + if (gtl::ContainsKey(visited, unperformed)) { return false; } visited.insert(unperformed); @@ -455,7 +455,7 @@ void IdToElementMap(AssignmentContainer* container, if (name.empty()) { LOG(INFO) << "Cannot save/load variables with empty name" << "; variable will be ignored"; - } else if (ContainsKey(*id_to_element_map, name)) { + } else if (gtl::ContainsKey(*id_to_element_map, name)) { LOG(INFO) << "Cannot save/load variables with duplicate names: " << name << "; variable will be ignored"; } else { @@ -470,7 +470,7 @@ void LoadElement(const std::unordered_map& id_to_element_map, const std::string& var_id = proto.var_id(); CHECK(!var_id.empty()); E* element = nullptr; - if (FindCopy(id_to_element_map, var_id, &element)) { + if (gtl::FindCopy(id_to_element_map, var_id, &element)) { element->LoadFromProto(proto); } else { LOG(INFO) << "Variable " << var_id diff --git a/ortools/constraint_solver/collect_variables.cc b/ortools/constraint_solver/collect_variables.cc index d6ed3aea87..dd1e5cf596 100644 --- a/ortools/constraint_solver/collect_variables.cc +++ b/ortools/constraint_solver/collect_variables.cc @@ -155,9 +155,9 @@ class CollectVariablesVisitor : public ModelParser { delegate->Accept(this); IgnoreIntegerVariable(const_cast(variable)); } else { - if (!ContainsKey(primary_set_, var) && - !ContainsKey(secondary_set_, var) && - !ContainsKey(ignored_set_, var) && !var->Bound()) { + if (!gtl::ContainsKey(primary_set_, var) && + !gtl::ContainsKey(secondary_set_, var) && + !gtl::ContainsKey(ignored_set_, var) && !var->Bound()) { primary_set_.insert(var); } } diff --git a/ortools/constraint_solver/constraint_solver.cc b/ortools/constraint_solver/constraint_solver.cc index fb0cea9530..bc45320e3d 100644 --- a/ortools/constraint_solver/constraint_solver.cc +++ b/ortools/constraint_solver/constraint_solver.cc @@ -983,7 +983,7 @@ class Search { jmpbuf_filled_(false), backtrack_at_the_end_of_the_search_(true) {} - ~Search() { STLDeleteElements(&marker_stack_); } + ~Search() { gtl::STLDeleteElements(&marker_stack_); } void EnterSearch(); void RestartSearch(); @@ -1443,7 +1443,7 @@ Solver::~Solver() { DCHECK_EQ(finalType, SENTINEL); // Not popping initial SENTINEL in Solver destructor. DCHECK_EQ(info.int_info, SOLVER_CTOR_SENTINEL); - STLDeleteElements(&searches_); + gtl::STLDeleteElements(&searches_); DeleteDemonProfiler(demon_profiler_); DeleteLocalSearchProfiler(local_search_profiler_); DeleteBuilders(); @@ -2411,7 +2411,8 @@ void Solver::RestartCurrentSearch() { // ----- Cast Expression ----- IntExpr* Solver::CastExpression(const IntVar* const var) const { - const IntegerCastInfo* const cast_info = FindOrNull(cast_information_, var); + const IntegerCastInfo* const cast_info = + gtl::FindOrNull(cast_information_, var); if (cast_info != nullptr) { return cast_info->expression; } @@ -2421,12 +2422,12 @@ IntExpr* Solver::CastExpression(const IntVar* const var) const { // --- Propagation object names --- std::string Solver::GetName(const PropagationBaseObject* object) { - const std::string* name = FindOrNull(propagation_object_names_, object); + const std::string* name = gtl::FindOrNull(propagation_object_names_, object); if (name != nullptr) { return *name; } const IntegerCastInfo* const cast_info = - FindOrNull(cast_information_, object); + gtl::FindOrNull(cast_information_, object); if (cast_info != nullptr && cast_info->expression != nullptr) { if (cast_info->expression->HasName()) { return StringPrintf("Var<%s>", cast_info->expression->name().c_str()); @@ -2458,8 +2459,8 @@ void Solver::SetName(const PropagationBaseObject* object, const std::string& nam } bool Solver::HasName(const PropagationBaseObject* const object) const { - return ContainsKey(propagation_object_names_, - const_cast(object)) || + return gtl::ContainsKey(propagation_object_names_, + const_cast(object)) || (!object->BaseName().empty() && parameters_.name_all_variables()); } @@ -3202,7 +3203,7 @@ void Constraint::Accept(ModelVisitor* const visitor) const { } bool Constraint::IsCastConstraint() const { - return ContainsKey(solver()->cast_constraints_, this); + return gtl::ContainsKey(solver()->cast_constraints_, this); } IntVar* Constraint::Var() { return nullptr; } diff --git a/ortools/constraint_solver/constraint_solver.h b/ortools/constraint_solver/constraint_solver.h index b7546c83b4..568d2be7d0 100644 --- a/ortools/constraint_solver/constraint_solver.h +++ b/ortools/constraint_solver/constraint_solver.h @@ -5024,7 +5024,7 @@ class AssignmentContainer { // but also how the map is hashed (e.g., number of buckets). This is not // what we want. for (const E& element : container.elements_) { - const int position = FindWithDefault(elements_map_, element.Var(), -1); + const int position = gtl::FindWithDefault(elements_map_, element.Var(), -1); if (position < 0 || elements_[position] != element) { return false; } @@ -5059,7 +5059,7 @@ class AssignmentContainer { } else { EnsureMapIsUpToDate(); DCHECK_EQ(elements_map_.size(), elements_.size()); - return FindCopy(elements_map_, var, index); + return gtl::FindCopy(elements_map_, var, index); } } diff --git a/ortools/constraint_solver/default_search.cc b/ortools/constraint_solver/default_search.cc index c009092cbd..3314f00ec2 100644 --- a/ortools/constraint_solver/default_search.cc +++ b/ortools/constraint_solver/default_search.cc @@ -399,7 +399,7 @@ class ImpactRecorder : public SearchMonitor { } d->Accept(&find_var_); if (find_var_.operation() == FindVar::ASSIGN && - ContainsKey(var_map_, find_var_.var())) { + gtl::ContainsKey(var_map_, find_var_.var())) { current_var_ = var_map_[find_var_.var()]; current_value_ = find_var_.value(); current_log_space_ = domain_watcher_->LogSearchSpaceSize(); @@ -912,7 +912,7 @@ class RestartMonitor : public SearchMonitor { const int64 value = choice.value(); if (choice.left()) { nogood->AddIntegerVariableEqualValueTerm(var, value); - } else if (!ContainsKey(positive_variable, choice.var())) { + } else if (!gtl::ContainsKey(positive_variable, choice.var())) { nogood->AddIntegerVariableNotEqualValueTerm(var, value); } } @@ -961,7 +961,7 @@ class RunHeuristicsAsDives : public Decision { Init(solver, vars, heuristic_num_failures_limit); } - ~RunHeuristicsAsDives() override { STLDeleteElements(&heuristics_); } + ~RunHeuristicsAsDives() override { gtl::STLDeleteElements(&heuristics_); } void Apply(Solver* const solver) override { if (!RunAllHeuristics(solver)) { diff --git a/ortools/constraint_solver/demon_profiler.cc b/ortools/constraint_solver/demon_profiler.cc index e0bde1fcde..16ee268bea 100644 --- a/ortools/constraint_solver/demon_profiler.cc +++ b/ortools/constraint_solver/demon_profiler.cc @@ -55,8 +55,8 @@ class DemonProfiler : public PropagationMonitor { start_time_ns_(absl::GetCurrentTimeNanos()) {} ~DemonProfiler() override { - STLDeleteContainerPairSecondPointers(constraint_map_.begin(), - constraint_map_.end()); + gtl::STLDeleteContainerPairSecondPointers(constraint_map_.begin(), + constraint_map_.end()); } // In microseconds. @@ -195,8 +195,8 @@ class DemonProfiler : public PropagationMonitor { // Restarts a search and clears all previously collected information. void RestartSearch() override { - STLDeleteContainerPairSecondPointers(constraint_map_.begin(), - constraint_map_.end()); + gtl::STLDeleteContainerPairSecondPointers(constraint_map_.begin(), + constraint_map_.end()); constraint_map_.clear(); demon_map_.clear(); demons_per_constraint_.clear(); diff --git a/ortools/constraint_solver/expr_cst.cc b/ortools/constraint_solver/expr_cst.cc index cea71ffdb7..e027b7f665 100644 --- a/ortools/constraint_solver/expr_cst.cc +++ b/ortools/constraint_solver/expr_cst.cc @@ -1192,7 +1192,7 @@ Constraint* Solver::MakeMemberCt(IntExpr* expr, // Catch empty set. if (copied_values.empty()) return MakeFalseConstraint(); // Sort and remove duplicates. - STLSortAndRemoveDuplicates(&copied_values); + gtl::STLSortAndRemoveDuplicates(&copied_values); // Special case for singleton. if (copied_values.size() == 1) return MakeEquality(expr, copied_values[0]); // Catch contiguous intervals. @@ -1261,7 +1261,7 @@ Constraint* Solver::MakeNotMemberCt(IntExpr* expr, // Catch empty set. if (copied_values.empty()) return MakeTrueConstraint(); // Sort and remove duplicates. - STLSortAndRemoveDuplicates(&copied_values); + gtl::STLSortAndRemoveDuplicates(&copied_values); // Special case for singleton. if (copied_values.size() == 1) return MakeNonEquality(expr, copied_values[0]); // Catch contiguous intervals. @@ -1318,7 +1318,7 @@ class IsMemberCt : public Constraint { DCHECK(v != nullptr); DCHECK(s != nullptr); DCHECK(b != nullptr); - while (ContainsKey(values_as_set_, neg_support_)) { + while (gtl::ContainsKey(values_as_set_, neg_support_)) { neg_support_++; } } @@ -1382,7 +1382,7 @@ class IsMemberCt : public Constraint { } else { // Look for a new negative support. for (const int64 value : InitAndGetValues(domain_)) { - if (!ContainsKey(values_as_set_, value)) { + if (!gtl::ContainsKey(values_as_set_, value)) { neg_support_ = value; return; } diff --git a/ortools/constraint_solver/expressions.cc b/ortools/constraint_solver/expressions.cc index c080ec876d..9b5da0a05d 100644 --- a/ortools/constraint_solver/expressions.cc +++ b/ortools/constraint_solver/expressions.cc @@ -6429,7 +6429,7 @@ IntVar* Solver::MakeIntVar(const std::vector& values, if (values.size() == 1) return MakeIntConst(values[0], name); // Sort and remove duplicates. std::vector unique_sorted_values = values; - STLSortAndRemoveDuplicates(&unique_sorted_values); + gtl::STLSortAndRemoveDuplicates(&unique_sorted_values); // Case when we have a single value, after clean-up. if (unique_sorted_values.size() == 1) return MakeIntConst(values[0], name); // Case when the values are a dense interval of integers. diff --git a/ortools/constraint_solver/hybrid.cc b/ortools/constraint_solver/hybrid.cc index dfcb1e1dcf..74c9e981e3 100644 --- a/ortools/constraint_solver/hybrid.cc +++ b/ortools/constraint_solver/hybrid.cc @@ -293,7 +293,7 @@ class Linearizer : public ModelParser { void PopActive() { actives_.pop_back(); } void RegisterExpression(const IntExpr* const cp_expr) { - if (!ContainsKey(*translation_, cp_expr)) { + if (!gtl::ContainsKey(*translation_, cp_expr)) { MPVariable* const mp_var = mp_solver_->MakeIntVar(cp_expr->Min(), cp_expr->Max(), ""); (*translation_)[cp_expr] = mp_var; @@ -301,7 +301,7 @@ class Linearizer : public ModelParser { } void VisitSubExpression(IntExpr* const cp_expr) { - if (!ContainsKey(*translation_, cp_expr)) { + if (!gtl::ContainsKey(*translation_, cp_expr)) { cp_expr->Accept(this); } } @@ -313,7 +313,7 @@ class Linearizer : public ModelParser { } MPVariable* Translated(const IntExpr* const cp_expr) { - return FindOrDie((*translation_), cp_expr); + return gtl::FindOrDie((*translation_), cp_expr); } void VisitBinaryRowConstraint(double lhs, double rhs) { diff --git a/ortools/constraint_solver/io.cc b/ortools/constraint_solver/io.cc index 93b9b4d343..9b4c8692a7 100644 --- a/ortools/constraint_solver/io.cc +++ b/ortools/constraint_solver/io.cc @@ -181,7 +181,7 @@ class FirstPassVisitor : public ModelVisitor { private: void Register(const IntExpr* const expression) { - if (!ContainsKey(expression_map_, expression)) { + if (!gtl::ContainsKey(expression_map_, expression)) { const int index = expression_map_.size(); CHECK_EQ(index, expression_list_.size()); expression_map_[expression] = index; @@ -194,7 +194,7 @@ class FirstPassVisitor : public ModelVisitor { } void Register(const IntervalVar* const interval) { - if (!ContainsKey(interval_map_, interval)) { + if (!gtl::ContainsKey(interval_map_, interval)) { const int index = interval_map_.size(); CHECK_EQ(index, interval_list_.size()); interval_map_[interval] = index; @@ -203,7 +203,7 @@ class FirstPassVisitor : public ModelVisitor { } void Register(const SequenceVar* const sequence) { - if (!ContainsKey(sequence_map_, sequence)) { + if (!gtl::ContainsKey(sequence_map_, sequence)) { const int index = sequence_map_.size(); CHECK_EQ(index, sequence_list_.size()); sequence_map_[sequence] = index; @@ -212,19 +212,19 @@ class FirstPassVisitor : public ModelVisitor { } void VisitSubArgument(IntExpr* const expression) { - if (!ContainsKey(expression_map_, expression)) { + if (!gtl::ContainsKey(expression_map_, expression)) { expression->Accept(this); } } void VisitSubArgument(IntervalVar* const interval) { - if (!ContainsKey(interval_map_, interval)) { + if (!gtl::ContainsKey(interval_map_, interval)) { interval->Accept(this); } } void VisitSubArgument(SequenceVar* const sequence) { - if (!ContainsKey(sequence_map_, sequence)) { + if (!gtl::ContainsKey(sequence_map_, sequence)) { sequence->Accept(this); } } @@ -388,15 +388,15 @@ class ArgumentHolder { } int64 FindIntegerArgumentWithDefault(const std::string& arg_name, int64 def) { - return FindWithDefault(integer_argument_, arg_name, def); + return gtl::FindWithDefault(integer_argument_, arg_name, def); } int64 FindIntegerArgumentOrDie(const std::string& arg_name) { - return FindOrDie(integer_argument_, arg_name); + return gtl::FindOrDie(integer_argument_, arg_name); } int64 FindIntegerExpressionArgumentOrDie(const std::string& arg_name) { - return FindOrDie(integer_expression_argument_, arg_name); + return gtl::FindOrDie(integer_expression_argument_, arg_name); } private: @@ -781,7 +781,7 @@ class SecondPassVisitor : public ModelVisitor { CHECK(!holders_.empty()); delete holders_.back(); holders_.pop_back(); - STLDeleteElements(&extensions_); + gtl::STLDeleteElements(&extensions_); extensions_.clear(); } @@ -802,15 +802,15 @@ class SecondPassVisitor : public ModelVisitor { } int FindExpressionIndexOrDie(IntExpr* const expression) const { - return FindOrDie(expression_map_, expression); + return gtl::FindOrDie(expression_map_, expression); } int FindIntervalIndexOrDie(IntervalVar* const interval) const { - return FindOrDie(interval_map_, interval); + return gtl::FindOrDie(interval_map_, interval); } int FindSequenceIndexOrDie(SequenceVar* const sequence) const { - return FindOrDie(sequence_map_, sequence); + return gtl::FindOrDie(sequence_map_, sequence); } std::unordered_map expression_map_; @@ -2534,45 +2534,45 @@ bool Solver::UpgradeModel(CpModel* const proto) { } void Solver::RegisterBuilder(const std::string& tag, ConstraintBuilder builder) { - InsertOrDie(&constraint_builders_, tag, builder); + gtl::InsertOrDie(&constraint_builders_, tag, builder); } void Solver::RegisterBuilder(const std::string& tag, IntegerExpressionBuilder builder) { - InsertOrDie(&expression_builders_, tag, builder); + gtl::InsertOrDie(&expression_builders_, tag, builder); } void Solver::RegisterBuilder(const std::string& tag, IntervalVariableBuilder builder) { - InsertOrDie(&interval_builders_, tag, builder); + gtl::InsertOrDie(&interval_builders_, tag, builder); } void Solver::RegisterBuilder(const std::string& tag, SequenceVariableBuilder builder) { - InsertOrDie(&sequence_builders_, tag, builder); + gtl::InsertOrDie(&sequence_builders_, tag, builder); } Solver::ConstraintBuilder Solver::GetConstraintBuilder( const std::string& tag) const { - return FindWithDefault(constraint_builders_, tag, nullptr); + return gtl::FindWithDefault(constraint_builders_, tag, nullptr); } Solver::IntegerExpressionBuilder Solver::GetIntegerExpressionBuilder( const std::string& tag) const { - return FindWithDefault(expression_builders_, tag, nullptr); + return gtl::FindWithDefault(expression_builders_, tag, nullptr); } Solver::IntervalVariableBuilder Solver::GetIntervalVariableBuilder( const std::string& tag) const { IntervalVariableBuilder builder = - FindWithDefault(interval_builders_, tag, nullptr); + gtl::FindWithDefault(interval_builders_, tag, nullptr); return builder; } Solver::SequenceVariableBuilder Solver::GetSequenceVariableBuilder( const std::string& tag) const { SequenceVariableBuilder builder = - FindWithDefault(sequence_builders_, tag, nullptr); + gtl::FindWithDefault(sequence_builders_, tag, nullptr); return builder; } diff --git a/ortools/constraint_solver/local_search.cc b/ortools/constraint_solver/local_search.cc index ffba8bb2ef..bfdb971f76 100644 --- a/ortools/constraint_solver/local_search.cc +++ b/ortools/constraint_solver/local_search.cc @@ -587,7 +587,7 @@ void PathOperator::InitializePathStarts() { new_index = index; } for (int j = 0; j < base_nodes_.size(); ++j) { - if (base_paths_[j] == i && !ContainsKey(found_bases, j)) { + if (base_paths_[j] == i && !gtl::ContainsKey(found_bases, j)) { found_bases.insert(j); base_paths_[j] = new_index; // If the current position of the base node is a removed empty path, @@ -1376,7 +1376,7 @@ bool TSPLns::MakeNeighbor() { breaks_set.insert(base_node); while (breaks_set.size() < tsp_size_) { const int64 one_break = nodes[rand_.Uniform(nodes.size())]; - if (!ContainsKey(breaks_set, one_break)) { + if (!gtl::ContainsKey(breaks_set, one_break)) { breaks_set.insert(one_break); } } @@ -1392,7 +1392,7 @@ bool TSPLns::MakeNeighbor() { int64 node_path = Path(node); while (!IsPathEnd(node)) { int64 next = Next(node); - if (ContainsKey(breaks_set, node)) { + if (gtl::ContainsKey(breaks_set, node)) { breaks.push_back(node); meta_node_costs.push_back(cost); cost = 0; diff --git a/ortools/constraint_solver/model_cache.cc b/ortools/constraint_solver/model_cache.cc index 6202a75cc3..1dc1224dd3 100644 --- a/ortools/constraint_solver/model_cache.cc +++ b/ortools/constraint_solver/model_cache.cc @@ -445,18 +445,18 @@ class NonReversibleCache : public ModelCache { } ~NonReversibleCache() override { - STLDeleteElements(&var_constant_constraints_); - STLDeleteElements(&expr_expr_constraints_); - STLDeleteElements(&var_constant_constant_constraints_); - STLDeleteElements(&expr_expressions_); - STLDeleteElements(&expr_constant_expressions_); - STLDeleteElements(&expr_expr_expressions_); - STLDeleteElements(&var_constant_constant_expressions_); - STLDeleteElements(&var_constant_array_expressions_); - STLDeleteElements(&var_array_expressions_); - STLDeleteElements(&var_array_constant_array_expressions_); - STLDeleteElements(&var_array_constant_expressions_); - STLDeleteElements(&expr_expr_constant_expressions_); + gtl::STLDeleteElements(&var_constant_constraints_); + gtl::STLDeleteElements(&expr_expr_constraints_); + gtl::STLDeleteElements(&var_constant_constant_constraints_); + gtl::STLDeleteElements(&expr_expressions_); + gtl::STLDeleteElements(&expr_constant_expressions_); + gtl::STLDeleteElements(&expr_expr_expressions_); + gtl::STLDeleteElements(&var_constant_constant_expressions_); + gtl::STLDeleteElements(&var_constant_array_expressions_); + gtl::STLDeleteElements(&var_array_expressions_); + gtl::STLDeleteElements(&var_array_constant_array_expressions_); + gtl::STLDeleteElements(&var_array_constant_expressions_); + gtl::STLDeleteElements(&expr_expr_constant_expressions_); } void Clear() override { diff --git a/ortools/constraint_solver/nogoods.cc b/ortools/constraint_solver/nogoods.cc index f5bd86c5c1..d88c7f7350 100644 --- a/ortools/constraint_solver/nogoods.cc +++ b/ortools/constraint_solver/nogoods.cc @@ -106,7 +106,7 @@ class IntegerVariableNoGoodTerm : public NoGoodTerm { // ----- NoGood ----- -NoGood::~NoGood() { STLDeleteElements(&terms_); } +NoGood::~NoGood() { gtl::STLDeleteElements(&terms_); } void NoGood::AddIntegerVariableEqualValueTerm(IntVar* const var, int64 value) { terms_.push_back(new IntegerVariableNoGoodTerm(var, value, true)); @@ -162,7 +162,7 @@ class NaiveNoGoodManager : public NoGoodManager { explicit NaiveNoGoodManager(Solver* const solver) : NoGoodManager(solver) {} ~NaiveNoGoodManager() override { Clear(); } - void Clear() override { STLDeleteElements(&nogoods_); } + void Clear() override { gtl::STLDeleteElements(&nogoods_); } void Init() override {} diff --git a/ortools/constraint_solver/resource.cc b/ortools/constraint_solver/resource.cc index de6a07f5b3..c2b4de6253 100644 --- a/ortools/constraint_solver/resource.cc +++ b/ortools/constraint_solver/resource.cc @@ -446,7 +446,7 @@ class NotLast { NotLast(Solver* const solver, const std::vector& intervals, bool mirror, bool strict); - ~NotLast() { STLDeleteElements(&by_start_min_); } + ~NotLast() { gtl::STLDeleteElements(&by_start_min_); } bool Propagate(); @@ -546,7 +546,7 @@ class EdgeFinderAndDetectablePrecedences { EdgeFinderAndDetectablePrecedences(Solver* const solver, const std::vector& intervals, bool mirror, bool strict); - ~EdgeFinderAndDetectablePrecedences() { STLDeleteElements(&by_start_min_); } + ~EdgeFinderAndDetectablePrecedences() { gtl::STLDeleteElements(&by_start_min_); } int64 size() const { return by_start_min_.size(); } IntervalVar* interval(int index) { return by_start_min_[index]->interval; } void UpdateEst(); @@ -563,7 +563,7 @@ class EdgeFinderAndDetectablePrecedences { // use them must first sort them in the right order. // All of these vectors store the same set of objects. Therefore, at - // destruction time, STLDeleteElements should be called on only one of them. + // destruction time, gtl::STLDeleteElements should be called on only one of them. // It does not matter which one. ThetaTree theta_tree_; @@ -1403,8 +1403,8 @@ class EdgeFinder : public Constraint { has_zero_demand_tasks_(true) {} ~EdgeFinder() override { - STLDeleteElements(&tasks_); - STLDeleteValues(&update_map_); + gtl::STLDeleteElements(&tasks_); + gtl::STLDeleteValues(&update_map_); } void Post() override { @@ -1437,7 +1437,7 @@ class EdgeFinder : public Constraint { private: UpdatesForADemand* GetOrMakeUpdate(int64 demand_min) { - UpdatesForADemand* update = FindPtrOrNull(update_map_, demand_min); + UpdatesForADemand* update = gtl::FindPtrOrNull(update_map_, demand_min); if (update == nullptr) { update = new UpdatesForADemand(tasks_.size()); update_map_[demand_min] = update; @@ -1717,7 +1717,7 @@ class CumulativeTimeTable : public Constraint { profile_unique_time_.reserve(profile_max_size); } - ~CumulativeTimeTable() override { STLDeleteElements(&by_start_min_); } + ~CumulativeTimeTable() override { gtl::STLDeleteElements(&by_start_min_); } void InitialPropagate() override { BuildProfile(); @@ -1917,7 +1917,7 @@ class TimeTableSync : public Constraint { demands_.reserve(num_tasks_); } - ~TimeTableSync() override { STLDeleteElements(&tasks_); } + ~TimeTableSync() override { gtl::STLDeleteElements(&tasks_); } void InitialPropagate() override { // Reset data structures. diff --git a/ortools/constraint_solver/routing.cc b/ortools/constraint_solver/routing.cc index 06eb8c3aa6..e4e341d9d9 100644 --- a/ortools/constraint_solver/routing.cc +++ b/ortools/constraint_solver/routing.cc @@ -402,8 +402,8 @@ class StateDependentRoutingCache : public RoutingModel::VariableNodeEvaluator2 { index_functions_delete.insert(transit.transit_plus_identity); } } - STLDeleteElements(&value_functions_delete); - STLDeleteElements(&index_functions_delete); + gtl::STLDeleteElements(&value_functions_delete); + gtl::STLDeleteElements(&index_functions_delete); } bool IsRepeatable() const override { return true; } // This method returns cached results of the callback. @@ -638,9 +638,9 @@ void RoutingModel::InitializeBuilders(Solver* solver) { } RoutingModel::~RoutingModel() { - STLDeleteElements(&owned_node_callbacks_); - STLDeleteElements(&dimensions_); - STLDeleteElements(&owned_state_dependent_callbacks_); + gtl::STLDeleteElements(&owned_node_callbacks_); + gtl::STLDeleteElements(&dimensions_); + gtl::STLDeleteElements(&owned_state_dependent_callbacks_); } RoutingModelParameters RoutingModel::DefaultModelParameters() { @@ -799,10 +799,10 @@ bool RoutingModel::InitializeDimensionInternal( delete dimension; std::unordered_set evaluator_set(evaluators.begin(), evaluators.end()); - STLDeleteElements(&evaluator_set); + gtl::STLDeleteElements(&evaluator_set); std::unordered_set dependent_evaluator_set( state_dependent_evaluators.begin(), state_dependent_evaluators.end()); - STLDeleteElements(&dependent_evaluator_set); + gtl::STLDeleteElements(&dependent_evaluator_set); return false; } } @@ -993,18 +993,18 @@ std::vector RoutingModel::GetAllDimensionNames() const { } bool RoutingModel::HasDimension(const std::string& dimension_name) const { - return ContainsKey(dimension_name_to_index_, dimension_name); + return gtl::ContainsKey(dimension_name_to_index_, dimension_name); } RoutingModel::DimensionIndex RoutingModel::GetDimensionIndex( const std::string& dimension_name) const { - return FindWithDefault(dimension_name_to_index_, dimension_name, + return gtl::FindWithDefault(dimension_name_to_index_, dimension_name, kNoDimension); } const RoutingDimension& RoutingModel::GetDimensionOrDie( const std::string& dimension_name) const { - return *dimensions_[FindOrDie(dimension_name_to_index_, dimension_name)]; + return *dimensions_[gtl::FindOrDie(dimension_name_to_index_, dimension_name)]; } RoutingDimension* RoutingModel::GetMutableDimension( @@ -1173,7 +1173,7 @@ void RoutingModel::ComputeCostClasses( // we can avoid to: we detect duplicate evaluators, for example, and if // there's only one evaluator callback used, we don't bother computing its // fingerprint. - if (!FindCopy(evaluator_to_fprint, uncached_evaluator, &evaluator_fprint)) { + if (!gtl::FindCopy(evaluator_to_fprint, uncached_evaluator, &evaluator_fprint)) { evaluator_fprint = all_evaluators_equal ? kAllEquivalentEvaluatorFprint @@ -1183,7 +1183,7 @@ void RoutingModel::ComputeCostClasses( evaluator_to_fprint[uncached_evaluator] = evaluator_fprint; } NodeEvaluator2** cached_evaluator = - &LookupOrInsert(&fprint_to_cached_evaluator, evaluator_fprint, nullptr); + >l::LookupOrInsert(&fprint_to_cached_evaluator, evaluator_fprint, nullptr); if (*cached_evaluator == nullptr) { *cached_evaluator = NewCachedCallback(uncached_evaluator); } @@ -1202,7 +1202,7 @@ void RoutingModel::ComputeCostClasses( // Try inserting the CostClass, if it's not already present. const CostClassIndex num_cost_classes(cost_classes_.size()); const CostClassIndex cost_class_index = - LookupOrInsert(&cost_class_map, cost_class, num_cost_classes); + gtl::LookupOrInsert(&cost_class_map, cost_class, num_cost_classes); if (cost_class_index == kCostClassIndexOfZeroCost) { has_vehicle_with_zero_cost_class = true; } else if (cost_class_index == num_cost_classes) { // New cost class. @@ -1304,7 +1304,7 @@ void RoutingModel::ComputeVehicleClasses() { nodes_unvisitability_bitmask.get(), nodes_unvisitability_num_bytes); const VehicleClassIndex num_vehicle_classes(vehicle_classes_.size()); const VehicleClassIndex vehicle_class_index = - LookupOrInsert(&vehicle_class_map, vehicle_class, num_vehicle_classes); + gtl::LookupOrInsert(&vehicle_class_map, vehicle_class, num_vehicle_classes); if (vehicle_class_index == num_vehicle_classes) { // New vehicle class vehicle_classes_.push_back(vehicle_class); } @@ -1644,7 +1644,7 @@ class RoutingModelInspector : public ModelVisitor { for (int node = 0; node < model_->Size(); ++node) { const int component = same_vehicle_components_.GetClassRepresentative(node); - if (InsertIfNotPresent(&component_indices, component, component_index)) { + if (gtl::InsertIfNotPresent(&component_indices, component, component_index)) { ++component_index; } } @@ -1652,25 +1652,25 @@ class RoutingModelInspector : public ModelVisitor { for (int node = 0; node < model_->Size(); ++node) { const int component = same_vehicle_components_.GetClassRepresentative(node); - DCHECK(ContainsKey(component_indices, component)); + DCHECK(gtl::ContainsKey(component_indices, component)); model_->SetSameVehicleGroup( - node, FindWithDefault(component_indices, component, 0)); + node, gtl::FindWithDefault(component_indices, component, 0)); } // TODO(user): Perform transitive closure of dimension precedence graphs. // TODO(user): Have a single annotated precedence graph. } void EndVisitConstraint(const std::string& type_name, const Constraint* const constraint) override { - FindWithDefault(constraint_inspectors_, type_name, []() {})(); + gtl::FindWithDefault(constraint_inspectors_, type_name, []() {})(); } void VisitIntegerExpressionArgument(const std::string& type_name, IntExpr* const expr) override { - FindWithDefault(expr_inspectors_, type_name, + gtl::FindWithDefault(expr_inspectors_, type_name, [](const IntExpr* expr) {})(expr); } void VisitIntegerArrayArgument(const std::string& arg_name, const std::vector& values) override { - FindWithDefault(array_inspectors_, arg_name, + gtl::FindWithDefault(array_inspectors_, arg_name, [](const std::vector& int_array) {})(values); } @@ -1695,7 +1695,7 @@ class RoutingModelInspector : public ModelVisitor { const std::vector& int_array) { ends_argument_ = int_array; }; constraint_inspectors_[kNotMember] = [this]() { std::pair dim_index; - if (FindCopy(cumul_to_dim_indices_, expr_, &dim_index)) { + if (gtl::FindCopy(cumul_to_dim_indices_, expr_, &dim_index)) { RoutingDimension* const dimension = dim_index.first; const int index = dim_index.second; dimension->forbidden_intervals_[index].InsertIntervals(starts_argument_, @@ -1710,8 +1710,8 @@ class RoutingModelInspector : public ModelVisitor { constraint_inspectors_[kEquality] = [this]() { int left_index = 0; int right_index = 0; - if (FindCopy(vehicle_var_to_indices_, left_, &left_index) && - FindCopy(vehicle_var_to_indices_, right_, &right_index)) { + if (gtl::FindCopy(vehicle_var_to_indices_, left_, &left_index) && + gtl::FindCopy(vehicle_var_to_indices_, right_, &right_index)) { VLOG(2) << "Vehicle variables for " << left_index << " and " << right_index << " are equal."; same_vehicle_components_.AddArc(left_index, right_index); @@ -1722,8 +1722,8 @@ class RoutingModelInspector : public ModelVisitor { constraint_inspectors_[kLessOrEqual] = [this]() { std::pair left_index; std::pair right_index; - if (FindCopy(cumul_to_dim_indices_, left_, &left_index) && - FindCopy(cumul_to_dim_indices_, right_, &right_index)) { + if (gtl::FindCopy(cumul_to_dim_indices_, left_, &left_index) && + gtl::FindCopy(cumul_to_dim_indices_, right_, &right_index)) { RoutingDimension* const dimension = left_index.first; if (dimension == right_index.first) { VLOG(2) << "For dimension " << dimension->name() << ", cumul for " @@ -2057,13 +2057,13 @@ class RouteConstructor { // linear and that given we managed to build a solution would be stupid to // drop it now. for (int chain_index = 0; chain_index < chains_.size(); ++chain_index) { - if (!ContainsKey(deleted_chains_, chain_index)) { + if (!gtl::ContainsKey(deleted_chains_, chain_index)) { final_chains_.push_back(chains_[chain_index]); } } std::sort(final_chains_.begin(), final_chains_.end(), ChainComparator); for (int route_index = 0; route_index < routes_.size(); ++route_index) { - if (!ContainsKey(deleted_routes_, route_index)) { + if (!gtl::ContainsKey(deleted_routes_, route_index)) { final_routes_.push_back(routes_[route_index]); } } @@ -2164,8 +2164,8 @@ class RouteConstructor { while (it != route.end()) { const int previous = *it; const int64 cumul_previous = cumul; - InsertOrDie(&(new_possible_cumuls_[dimension_index]), previous, - cumul_previous); + gtl::InsertOrDie(&(new_possible_cumuls_[dimension_index]), previous, + cumul_previous); ++it; if (it == route.end()) { return true; @@ -2234,7 +2234,7 @@ class RouteConstructor { feasible_route = FeasibleRoute(route2, new_available_cumul_head2, dimension_index); const int64 new_possible_cumul_tail2 = - ContainsKey(new_possible_cumuls_[dimension_index], tail2) + gtl::ContainsKey(new_possible_cumuls_[dimension_index], tail2) ? new_possible_cumuls_[dimension_index][tail2] : cumuls_[dimension_index][tail2]; @@ -2294,7 +2294,7 @@ class RouteConstructor { for (int chain_index = 0; chain_index < chains_.size(); ++chain_index) { if ((chain_index != new_chain_index) && (chain_index != old_chain_index) && - (!ContainsKey(deleted_chains_, chain_index))) { + (!gtl::ContainsKey(deleted_chains_, chain_index))) { const int start = chains_[chain_index].head; const int end = chains_[chain_index].tail; temp_assignment->Add(model_->NextVar(model_->Start(chain_index))); @@ -3352,7 +3352,7 @@ bool RoutingModel::RoutesToAssignment( // Deactivate other nodes (by pointing them to themselves). if (close_routes) { for (int index = 0; index < Size(); ++index) { - if (!ContainsKey(visited_indices, index)) { + if (!gtl::ContainsKey(visited_indices, index)) { IntVar* const next_var = NextVar(index); if (!assignment->Contains(next_var)) { assignment->Add(next_var); @@ -3694,7 +3694,7 @@ std::string RoutingModel::DebugOutputAssignment( "%" GG_LL_FORMAT "d Vehicle(%" GG_LL_FORMAT "d) ", index, solution_assignment.Value(vehicle_var)); for (const RoutingDimension* const dimension : dimensions_) { - if (ContainsKey(dimension_names, dimension->name())) { + if (gtl::ContainsKey(dimension_names, dimension->name())) { const IntVar* const var = dimension->CumulVar(index); StringAppendF( &output, "%s(%" GG_LL_FORMAT "d..%" GG_LL_FORMAT "d) ", @@ -4438,7 +4438,7 @@ RoutingModel::NodeEvaluator2* RoutingModel::NewCachedCallback( const int size = node_to_index_.size(); if (cache_callbacks_) { NodeEvaluator2* cached_evaluator = nullptr; - if (!FindCopy(cached_node_callbacks_, callback, &cached_evaluator)) { + if (!gtl::FindCopy(cached_node_callbacks_, callback, &cached_evaluator)) { cached_evaluator = new RoutingCache(callback, size); cached_node_callbacks_[callback] = cached_evaluator; // Make sure that both the cache and the base callback get deleted @@ -4462,7 +4462,7 @@ RoutingModel::NewCachedStateDependentCallback( VariableNodeEvaluator2* callback) { const int size = node_to_index_.size(); VariableNodeEvaluator2* cached_evaluator = nullptr; - if (!FindCopy(cached_state_dependent_callbacks_, callback, + if (!gtl::FindCopy(cached_state_dependent_callbacks_, callback, &cached_evaluator)) { cached_evaluator = new StateDependentRoutingCache(callback, size); cached_state_dependent_callbacks_[callback] = cached_evaluator; @@ -4524,7 +4524,7 @@ int64 RoutingModel::GetTransitValue(const std::string& dimension_name, int64 from_index, int64 to_index, int64 vehicle) const { DimensionIndex dimension_index(-1); - if (FindCopy(dimension_name_to_index_, dimension_name, &dimension_index)) { + if (gtl::FindCopy(dimension_name_to_index_, dimension_name, &dimension_index)) { return dimensions_[dimension_index]->GetTransitValue(from_index, to_index, vehicle); } else { @@ -4780,7 +4780,7 @@ void ComputeTransitClasses(const std::vector& node_evaluators, for (int i = 0; i < node_evaluators.size(); ++i) { NodeEvaluator* const evaluator = node_evaluators[i]; int evaluator_class = -1; - if (!FindCopy(evaluator_to_class, evaluator, &evaluator_class)) { + if (!gtl::FindCopy(evaluator_to_class, evaluator, &evaluator_class)) { evaluator_class = class_evaluators->size(); evaluator_to_class[evaluator] = evaluator_class; class_evaluators->emplace_back([model, evaluator](int64 from, int64 to) { diff --git a/ortools/constraint_solver/routing_flags.cc b/ortools/constraint_solver/routing_flags.cc index 7b21dff83e..865eac715d 100644 --- a/ortools/constraint_solver/routing_flags.cc +++ b/ortools/constraint_solver/routing_flags.cc @@ -130,8 +130,8 @@ void SetFirstSolutionStrategyFromFlags(RoutingSearchParameters* parameters) { {"DefaultStrategy", FirstSolutionStrategy::FIRST_UNBOUND_MIN_VALUE}, {"", FirstSolutionStrategy::FIRST_UNBOUND_MIN_VALUE}}; FirstSolutionStrategy::Value strategy; - if (FindCopy(first_solution_string_to_parameters, - FLAGS_routing_first_solution, &strategy)) { + if (gtl::FindCopy(first_solution_string_to_parameters, + FLAGS_routing_first_solution, &strategy)) { parameters->set_first_solution_strategy(strategy); } parameters->set_use_filtered_first_solution_strategy( diff --git a/ortools/constraint_solver/routing_search.cc b/ortools/constraint_solver/routing_search.cc index 5f36ff078c..d461169bd1 100644 --- a/ortools/constraint_solver/routing_search.cc +++ b/ortools/constraint_solver/routing_search.cc @@ -99,17 +99,17 @@ class NodeDisjunctionFilter : public RoutingLocalSearchFilter { !IsVarSynced(index) || (Value(index) == index) != is_inactive; if (active_state_changed) { if (!is_inactive) { - ++LookupOrInsert(&disjunction_active_deltas, disjunction_index, + ++gtl::LookupOrInsert(&disjunction_active_deltas, disjunction_index, 0); if (IsVarSynced(index)) { - --LookupOrInsert(&disjunction_inactive_deltas, + --gtl::LookupOrInsert(&disjunction_inactive_deltas, disjunction_index, 0); } } else { - ++LookupOrInsert(&disjunction_inactive_deltas, disjunction_index, + ++gtl::LookupOrInsert(&disjunction_inactive_deltas, disjunction_index, 0); if (IsVarSynced(index)) { - --LookupOrInsert(&disjunction_active_deltas, disjunction_index, + --gtl::LookupOrInsert(&disjunction_active_deltas, disjunction_index, 0); } } @@ -1058,12 +1058,12 @@ bool PathCumulFilter::FinalizeAcceptPath() { // Delta max end is lower than the current solution one. // If the path supporting the current max end has been modified, we need // to check all paths to find the largest max end. - if (!ContainsKey(delta_paths_, current_max_end_.cumul_value_support)) { + if (!gtl::ContainsKey(delta_paths_, current_max_end_.cumul_value_support)) { new_max_end = current_max_end_.cumul_value; } else { for (int i = 0; i < current_max_end_.path_values.size(); ++i) { if (current_max_end_.path_values[i] > new_max_end && - !ContainsKey(delta_paths_, i)) { + !gtl::ContainsKey(delta_paths_, i)) { new_max_end = current_max_end_.path_values[i]; } } @@ -1079,7 +1079,7 @@ bool PathCumulFilter::FinalizeAcceptPath() { } if (new_max_end != current_max_end_.cumul_value) { for (int r = 0; r < NumPaths(); ++r) { - if (ContainsKey(delta_paths_, r)) { + if (gtl::ContainsKey(delta_paths_, r)) { continue; } new_min_start = std::min(new_min_start, @@ -1090,12 +1090,12 @@ bool PathCumulFilter::FinalizeAcceptPath() { // Delta min start is greater than the current solution one. // If the path supporting the current min start has been modified, we need // to check all paths to find the smallest min start. - if (!ContainsKey(delta_paths_, current_min_start_.cumul_value_support)) { + if (!gtl::ContainsKey(delta_paths_, current_min_start_.cumul_value_support)) { new_min_start = current_min_start_.cumul_value; } else { for (int i = 0; i < current_min_start_.path_values.size(); ++i) { if (current_min_start_.path_values[i] < new_min_start && - !ContainsKey(delta_paths_, i)) { + !gtl::ContainsKey(delta_paths_, i)) { new_min_start = current_min_start_.path_values[i]; } } @@ -1909,7 +1909,7 @@ void GlobalCheapestInsertionFilteredDecisionBuilder::UpdatePickupPositions( while (!model()->IsEnd(delivery_insert_after)) { const std::pair insertion = {{pickup, delivery}, delivery_insert_after}; - if (!ContainsKey(existing_insertions, insertion)) { + if (!gtl::ContainsKey(existing_insertions, insertion)) { PairEntry* const entry = new PairEntry(pickup, pickup_insert_after, delivery, delivery_insert_after, vehicle); @@ -2009,7 +2009,7 @@ void GlobalCheapestInsertionFilteredDecisionBuilder::UpdateDeliveryPositions( while (pickup_insert_after != delivery_insert_after) { std::pair insertion = {{pickup, delivery}, pickup_insert_after}; - if (!ContainsKey(existing_insertions, insertion)) { + if (!gtl::ContainsKey(existing_insertions, insertion)) { PairEntry* const entry = new PairEntry(pickup, pickup_insert_after, delivery, delivery_insert_after, vehicle); diff --git a/ortools/constraint_solver/sat_constraint.cc b/ortools/constraint_solver/sat_constraint.cc index f8f0f13588..e25815553a 100644 --- a/ortools/constraint_solver/sat_constraint.cc +++ b/ortools/constraint_solver/sat_constraint.cc @@ -87,8 +87,8 @@ void SatTableConstraint::Post() { } int BooleanVariableManager::RegisterIntVar(IntVar* int_var) { - const int reg_index = LookupOrInsert(®istration_index_map_, int_var, - registered_int_vars_.size()); + const int reg_index = gtl::LookupOrInsert(®istration_index_map_, int_var, + registered_int_vars_.size()); if (reg_index < registered_int_vars_.size()) return reg_index; registered_int_vars_.push_back(int_var); diff --git a/ortools/constraint_solver/sched_search.cc b/ortools/constraint_solver/sched_search.cc index aeae750f88..41213c1867 100644 --- a/ortools/constraint_solver/sched_search.cc +++ b/ortools/constraint_solver/sched_search.cc @@ -131,7 +131,7 @@ void SequenceVar::ActiveHorizonRange(int64* const hmin, int64 hor_min = kint64max; int64 hor_max = kint64min; for (int i = 0; i < intervals_.size(); ++i) { - if (!ContainsKey(decided, i)) { + if (!gtl::ContainsKey(decided, i)) { IntervalVar* const t = intervals_[i]; hor_min = std::min(hor_min, t->StartMin()); hor_max = std::max(hor_max, t->EndMax()); diff --git a/ortools/constraint_solver/search.cc b/ortools/constraint_solver/search.cc index f804b7831a..4144923aaa 100644 --- a/ortools/constraint_solver/search.cc +++ b/ortools/constraint_solver/search.cc @@ -2154,7 +2154,7 @@ SolutionCollector::~SolutionCollector() { for (auto& data : solution_data_) { delete data.solution; } - STLDeleteElements(&recycle_solutions_); + gtl::STLDeleteElements(&recycle_solutions_); } void SolutionCollector::Add(IntVar* const var) { @@ -2203,7 +2203,7 @@ void SolutionCollector::EnterSearch() { for (auto& data : solution_data_) { delete data.solution; } - STLDeleteElements(&recycle_solutions_); + gtl::STLDeleteElements(&recycle_solutions_); solution_data_.clear(); recycle_solutions_.clear(); } @@ -3322,7 +3322,7 @@ void GuidedLocalSearchPenaltiesMap::Reset() { int64 GuidedLocalSearchPenaltiesMap::Value(const Arc& arc) const { if (penalized_.Get(arc.first)) { - return FindWithDefault(penalties_, arc, 0LL); + return gtl::FindWithDefault(penalties_, arc, 0LL); } return 0LL; } @@ -3527,7 +3527,7 @@ int64 GuidedLocalSearch::Evaluate(const Assignment* delta, const IntVarElement& new_element = container.Element(i); IntVar* var = new_element.Var(); int64 index = -1; - if (FindCopy(indices_, var, &index)) { + if (gtl::FindCopy(indices_, var, &index)) { penalty -= out_values[index]; int64 new_penalty = 0; if (EvaluateElementValue(container, index, &i, &new_penalty)) { diff --git a/ortools/constraint_solver/table.cc b/ortools/constraint_solver/table.cc index c0a1809a62..67c2f3d967 100644 --- a/ortools/constraint_solver/table.cc +++ b/ortools/constraint_solver/table.cc @@ -303,7 +303,7 @@ class PositiveTableConstraint : public BasePositiveTableConstraint { IntVar* const var = vars_[var_index]; to_remove_.clear(); for (const int64 value : InitAndGetValues(iterators_[var_index])) { - if (!ContainsKey(mask, value)) { + if (!gtl::ContainsKey(mask, value)) { to_remove_.push_back(value); } } @@ -366,7 +366,7 @@ class PositiveTableConstraint : public BasePositiveTableConstraint { bool Supported(int var_index, int64 value) { DCHECK_GE(var_index, 0); DCHECK_LT(var_index, arity_); - DCHECK(ContainsKey(masks_[var_index], value)); + DCHECK(gtl::ContainsKey(masks_[var_index], value)); const std::vector& mask = masks_[var_index][value]; int tmp = 0; return active_tuples_.Intersects(mask, &tmp); diff --git a/ortools/constraint_solver/tree_monitor.cc b/ortools/constraint_solver/tree_monitor.cc index 43c763d910..836d4cc05c 100644 --- a/ortools/constraint_solver/tree_monitor.cc +++ b/ortools/constraint_solver/tree_monitor.cc @@ -262,7 +262,7 @@ class TreeNode { TreeNode(TreeNode* parent, int id) : cycles_(1), id_(id), name_(""), node_type_(TRY), parent_(parent) {} - ~TreeNode() { STLDeleteElements(&children_); } + ~TreeNode() { gtl::STLDeleteElements(&children_); } // Gets the value of a decision's branch. int64 branch_value(int branch) const { return branch_values_[branch]; } @@ -322,7 +322,7 @@ class TreeNode { for (int i = 0; i < children_.size(); ++i) { // Reuse existing branch if possible if (children_[i]->name_ == name && - branch_values_[i] == FindOrDie(last_value, name_)) { + branch_values_[i] == gtl::FindOrDie(last_value, name_)) { children_[i]->AddCycle(); *child = children_[i]; return false; @@ -334,7 +334,7 @@ class TreeNode { tree_node->set_name(name); tree_node->SetDomain(vars); children_.push_back(tree_node); - branch_values_.push_back(FindOrDie(last_value, name_)); + branch_values_.push_back(gtl::FindOrDie(last_value, name_)); *child = tree_node; return true; @@ -438,7 +438,7 @@ class TreeNode { : domain_; const std::vector* const domain_values = - FindOrNull(domain, name_); + gtl::FindOrNull(domain, name_); if (domain_values) { tree_writer->AddAttribute("size", StrCat(domain_values->size())); } else { diff --git a/ortools/constraint_solver/utilities.cc b/ortools/constraint_solver/utilities.cc index 2a09db44d5..c85845fde4 100644 --- a/ortools/constraint_solver/utilities.cc +++ b/ortools/constraint_solver/utilities.cc @@ -666,7 +666,7 @@ class ModelStatisticsVisitor : public ModelVisitor { } bool AlreadyVisited(const BaseObject* const object) { - return ContainsKey(already_visited_, object); + return gtl::ContainsKey(already_visited_, object); } // T should derive from BaseObject @@ -716,7 +716,7 @@ class VariableDegreeVisitor : public ModelVisitor { void VisitIntegerVariable(const IntVar* const variable, IntExpr* const delegate) override { IntVar* const var = const_cast(variable); - if (ContainsKey(*map_, var)) { + if (gtl::ContainsKey(*map_, var)) { (*map_)[var]++; } if (delegate) { @@ -728,7 +728,7 @@ class VariableDegreeVisitor : public ModelVisitor { const std::string& operation, int64 value, IntVar* const delegate) override { IntVar* const var = const_cast(variable); - if (ContainsKey(*map_, var)) { + if (gtl::ContainsKey(*map_, var)) { (*map_)[var]++; } VisitSubArgument(delegate); diff --git a/ortools/constraint_solver/visitor.cc b/ortools/constraint_solver/visitor.cc index 64f67aed88..79515e04e2 100644 --- a/ortools/constraint_solver/visitor.cc +++ b/ortools/constraint_solver/visitor.cc @@ -82,42 +82,42 @@ void ArgumentHolder::SetSequenceArrayArgument( bool ArgumentHolder::HasIntegerExpressionArgument( const std::string& arg_name) const { - return ContainsKey(integer_expression_argument_, arg_name); + return gtl::ContainsKey(integer_expression_argument_, arg_name); } bool ArgumentHolder::HasIntegerVariableArrayArgument( const std::string& arg_name) const { - return ContainsKey(integer_variable_array_argument_, arg_name); + return gtl::ContainsKey(integer_variable_array_argument_, arg_name); } int64 ArgumentHolder::FindIntegerArgumentWithDefault(const std::string& arg_name, int64 def) const { - return FindWithDefault(integer_argument_, arg_name, def); + return gtl::FindWithDefault(integer_argument_, arg_name, def); } int64 ArgumentHolder::FindIntegerArgumentOrDie(const std::string& arg_name) const { - return FindOrDie(integer_argument_, arg_name); + return gtl::FindOrDie(integer_argument_, arg_name); } const std::vector& ArgumentHolder::FindIntegerArrayArgumentOrDie( const std::string& arg_name) const { - return FindOrDie(integer_array_argument_, arg_name); + return gtl::FindOrDie(integer_array_argument_, arg_name); } IntExpr* ArgumentHolder::FindIntegerExpressionArgumentOrDie( const std::string& arg_name) const { - return FindOrDie(integer_expression_argument_, arg_name); + return gtl::FindOrDie(integer_expression_argument_, arg_name); } const std::vector& ArgumentHolder::FindIntegerVariableArrayArgumentOrDie( const std::string& arg_name) const { - return FindOrDie(integer_variable_array_argument_, arg_name); + return gtl::FindOrDie(integer_variable_array_argument_, arg_name); } const IntTupleSet& ArgumentHolder::FindIntegerMatrixArgumentOrDie( const std::string& arg_name) const { - return FindOrDie(matrix_argument_, arg_name); + return gtl::FindOrDie(matrix_argument_, arg_name); } // ---------- ModelParser --------- diff --git a/ortools/flatzinc/checker.cc b/ortools/flatzinc/checker.cc index 61519f84c5..98a3ab42da 100644 --- a/ortools/flatzinc/checker.cc +++ b/ortools/flatzinc/checker.cc @@ -71,7 +71,7 @@ bool CheckAllDifferentInt( std::unordered_set visited; for (int i = 0; i < Size(ct.arguments[0]); ++i) { const int64 value = EvalAt(ct.arguments[0], i, evaluator); - if (ContainsKey(visited, value)) { + if (gtl::ContainsKey(visited, value)) { return false; } visited.insert(value); @@ -86,7 +86,7 @@ bool CheckAlldifferentExcept0( std::unordered_set visited; for (int i = 0; i < Size(ct.arguments[0]); ++i) { const int64 value = EvalAt(ct.arguments[0], i, evaluator); - if (value != 0 && ContainsKey(visited, value)) { + if (value != 0 && gtl::ContainsKey(visited, value)) { return false; } visited.insert(value); @@ -403,7 +403,7 @@ std::vector ComputeGlobalCardinalityCards( } for (int i = 0; i < Size(ct.arguments[0]); ++i) { const int value = EvalAt(ct.arguments[0], i, evaluator); - if (ContainsKey(positions, value)) { + if (gtl::ContainsKey(positions, value)) { cards[positions[value]]++; } } @@ -1163,7 +1163,7 @@ bool CheckSolution(const Model& model, const CallMap call_map = CreateCallMap(); for (Constraint* ct : model.constraints()) { if (!ct->active) continue; - const auto& checker = FindOrDie(call_map, ct->type); + const auto& checker = gtl::FindOrDie(call_map, ct->type); if (!checker(*ct, evaluator)) { FZLOG << "Failing constraint " << ct->DebugString() << FZENDL; ok = false; diff --git a/ortools/flatzinc/constraints.cc b/ortools/flatzinc/constraints.cc index 843c7aaf7c..f72446b1f1 100644 --- a/ortools/flatzinc/constraints.cc +++ b/ortools/flatzinc/constraints.cc @@ -218,7 +218,7 @@ void ExtractArrayBoolAnd(fz::SolverData* data, fz::Constraint* ct) { const std::vector tmp_vars = data->GetOrCreateVariableArray(ct->arguments[0]); for (IntVar* const to_add : tmp_vars) { - if (!ContainsKey(added, to_add) && to_add->Min() != 1) { + if (!gtl::ContainsKey(added, to_add) && to_add->Min() != 1) { variables.push_back(to_add); added.insert(to_add); } @@ -271,7 +271,7 @@ void ExtractArrayBoolOr(fz::SolverData* data, fz::Constraint* ct) { const std::vector tmp_vars = data->GetOrCreateVariableArray(ct->arguments[0]); for (IntVar* const to_add : tmp_vars) { - if (!ContainsKey(added, to_add) && to_add->Max() != 0) { + if (!gtl::ContainsKey(added, to_add) && to_add->Max() != 0) { variables.push_back(to_add); added.insert(to_add); } diff --git a/ortools/flatzinc/cp_model_fz_solver.cc b/ortools/flatzinc/cp_model_fz_solver.cc index 4cfc7c66f0..704b86c139 100644 --- a/ortools/flatzinc/cp_model_fz_solver.cc +++ b/ortools/flatzinc/cp_model_fz_solver.cc @@ -91,7 +91,7 @@ struct CpModelProtoWithMapping { }; int CpModelProtoWithMapping::LookupConstant(int64 value) { - if (ContainsKey(constant_value_to_index, value)) { + if (gtl::ContainsKey(constant_value_to_index, value)) { return constant_value_to_index[value]; } @@ -687,7 +687,7 @@ void CpModelProtoWithMapping::TranslateSearchAnnotations( DecisionStrategyProto* strategy = proto.add_search_strategy(); for (fz::IntegerVariable* v : vars) { - strategy->add_variables(FindOrDie(fz_var_to_index, v)); + strategy->add_variables(gtl::FindOrDie(fz_var_to_index, v)); } const fz::Annotation& choose = args[1]; @@ -756,7 +756,7 @@ std::string SolutionString( } } else { const int bound_size = output.bounds.size(); - std::string result = StrCat(output.name, " = array", bound_size, "d("); + std::string result = absl::StrCat(output.name, " = array", bound_size, "d("); for (int i = 0; i < bound_size; ++i) { if (output.bounds[i].max_value != 0) { absl::StrAppend(&result, output.bounds[i].min_value, "..", diff --git a/ortools/flatzinc/model.cc b/ortools/flatzinc/model.cc index 9f510d76ed..76195fa846 100644 --- a/ortools/flatzinc/model.cc +++ b/ortools/flatzinc/model.cc @@ -34,7 +34,7 @@ Domain Domain::IntegerList(std::vector values) { Domain result; result.is_interval = false; result.values = std::move(values); - STLSortAndRemoveDuplicates(&result.values); + gtl::STLSortAndRemoveDuplicates(&result.values); result.display_as_boolean = false; result.is_a_set = false; return result; @@ -198,7 +198,7 @@ bool Domain::IntersectWithListOfIntegers(const std::vector& integers) { for (const int64 v : integers) { if (v >= dmin && v <= dmax) values.push_back(v); } - STLSortAndRemoveDuplicates(&values); + gtl::STLSortAndRemoveDuplicates(&values); if (!values.empty() && values.back() - values.front() == values.size() - 1 && values.size() >= 2) { @@ -222,7 +222,7 @@ bool Domain::IntersectWithListOfIntegers(const std::vector& integers) { new_values.reserve(std::min(values.size(), integers.size())); bool changed = false; for (const int64 val : values) { - if (ContainsKey(other_values, val)) { + if (gtl::ContainsKey(other_values, val)) { if (new_values.empty() || val != new_values.back()) { new_values.push_back(val); } @@ -304,7 +304,7 @@ bool Domain::OverlapsIntList(const std::vector& vec) const { ? std::unordered_set(vec.begin(), vec.end()) : std::unordered_set(values.begin(), values.end()); for (int64 value : to_scan) { - if (ContainsKey(container, value)) { + if (gtl::ContainsKey(container, value)) { return true; } } @@ -378,7 +378,7 @@ std::string Domain::DebugString() const { values[0], values[1]); } } else if (values.size() == 1) { - return StrCat(values.back()); + return absl::StrCat(values.back()); } else { return StringPrintf("[%s]", absl::StrJoin(values, ", ").c_str()); } @@ -593,7 +593,7 @@ IntegerVariable::IntegerVariable(const std::string& name_, const Domain& domain_ temporary(temporary_), active(true) { if (!domain.is_interval) { - STLSortAndRemoveDuplicates(&domain.values); + gtl::STLSortAndRemoveDuplicates(&domain.values); } } @@ -793,7 +793,7 @@ std::string Annotation::DebugString() const { interval_min, interval_max); } case INT_VALUE: { - return StrCat(interval_min); + return absl::StrCat(interval_min); } case INT_VAR_REF: { return variables.front()->name; @@ -862,8 +862,8 @@ std::string SolutionOutputSpecs::DebugString() const { // ----- Model ----- Model::~Model() { - STLDeleteElements(&variables_); - STLDeleteElements(&constraints_); + gtl::STLDeleteElements(&variables_); + gtl::STLDeleteElements(&constraints_); } IntegerVariable* Model::AddVariable(const std::string& name, const Domain& domain, @@ -875,8 +875,8 @@ IntegerVariable* Model::AddVariable(const std::string& name, const Domain& domai // TODO(user): Create only once constant per value. IntegerVariable* Model::AddConstant(int64 value) { - IntegerVariable* const var = - new IntegerVariable(StrCat(value), Domain::IntegerValue(value), true); + IntegerVariable* const var = new IntegerVariable( + absl::StrCat(value), Domain::IntegerValue(value), true); variables_.push_back(var); return var; } diff --git a/ortools/flatzinc/presolve.cc b/ortools/flatzinc/presolve.cc index 834546751e..e561a62135 100644 --- a/ortools/flatzinc/presolve.cc +++ b/ortools/flatzinc/presolve.cc @@ -301,13 +301,13 @@ Presolver::RuleStatus Presolver::PresolveIntEq(Constraint* ct, std::string* log) // Rule 1 if (ct->arguments[0].IsVariable() && ct->arguments[1].HasOneValue() && ct->arguments[1].Value() == 0 && - ContainsKey(difference_map_, ct->arguments[0].Var())) { + gtl::ContainsKey(difference_map_, ct->arguments[0].Var())) { log->append("propagate equality"); IntersectVarWithSingleton(ct->arguments[0].Var(), 0); log->append(", transform null differences"); const std::pair& diff = - FindOrDie(difference_map_, ct->arguments[0].Var()); + gtl::FindOrDie(difference_map_, ct->arguments[0].Var()); ct->arguments[0] = Argument::IntVarRef(diff.first); ct->arguments[1] = Argument::IntVarRef(diff.second); return CONSTRAINT_REWRITTEN; @@ -1485,7 +1485,7 @@ Presolver::RuleStatus Presolver::RegroupLinear(Constraint* ct, std::string* log) for (int i = 0; i < original_size; ++i) { IntegerVariable* fz_var = ct->arguments[1].variables[i]; const int64 coefficient = coefficients[fz_var]; - if (!ContainsKey(processed, fz_var)) { + if (!gtl::ContainsKey(processed, fz_var)) { processed.insert(fz_var); if (coefficient != 0) { ct->arguments[1].variables[index] = fz_var; @@ -1688,7 +1688,7 @@ Presolver::RuleStatus Presolver::PresolveStoreMapping(Constraint* ct, if (ct->arguments[0].values.size() == 2 && ct->arguments[1].variables[0] == ct->target_variable && ct->arguments[0].values[0] == -1 && - !ContainsKey(affine_map_, ct->target_variable) && + !gtl::ContainsKey(affine_map_, ct->target_variable) && ct->strong_propagation) { affine_map_[ct->target_variable] = AffineMapping(ct->arguments[1].variables[1], ct->arguments[0].values[1], @@ -1700,7 +1700,7 @@ Presolver::RuleStatus Presolver::PresolveStoreMapping(Constraint* ct, if (ct->arguments[0].values.size() == 2 && ct->arguments[1].variables[1] == ct->target_variable && ct->arguments[0].values[1] == -1 && - !ContainsKey(affine_map_, ct->target_variable)) { + !gtl::ContainsKey(affine_map_, ct->target_variable)) { affine_map_[ct->target_variable] = AffineMapping(ct->arguments[1].variables[0], ct->arguments[0].values[0], -ct->arguments[2].Value(), ct); @@ -1711,7 +1711,7 @@ Presolver::RuleStatus Presolver::PresolveStoreMapping(Constraint* ct, if (ct->arguments[0].values.size() == 3 && ct->arguments[1].variables[0] == ct->target_variable && ct->arguments[0].values[0] == -1 && ct->arguments[0].values[2] == 1 && - !ContainsKey(array2d_index_map_, ct->target_variable) && + !gtl::ContainsKey(array2d_index_map_, ct->target_variable) && ct->strong_propagation) { array2d_index_map_[ct->target_variable] = Array2DIndexMapping( ct->arguments[1].variables[1], ct->arguments[0].values[1], @@ -1723,7 +1723,7 @@ Presolver::RuleStatus Presolver::PresolveStoreMapping(Constraint* ct, if (ct->arguments[0].values.size() == 3 && ct->arguments[1].variables[0] == ct->target_variable && ct->arguments[0].values[0] == -1 && ct->arguments[0].values[1] == 1 && - !ContainsKey(array2d_index_map_, ct->target_variable) && + !gtl::ContainsKey(array2d_index_map_, ct->target_variable) && ct->strong_propagation) { array2d_index_map_[ct->target_variable] = Array2DIndexMapping( ct->arguments[1].variables[2], ct->arguments[0].values[2], @@ -1735,7 +1735,7 @@ Presolver::RuleStatus Presolver::PresolveStoreMapping(Constraint* ct, if (ct->arguments[0].values.size() == 3 && ct->arguments[1].variables[2] == ct->target_variable && ct->arguments[0].values[2] == -1 && ct->arguments[0].values[1] == 1 && - !ContainsKey(array2d_index_map_, ct->target_variable)) { + !gtl::ContainsKey(array2d_index_map_, ct->target_variable)) { array2d_index_map_[ct->target_variable] = Array2DIndexMapping( ct->arguments[1].variables[0], ct->arguments[0].values[0], ct->arguments[1].variables[1], -ct->arguments[2].Value(), ct); @@ -1746,7 +1746,7 @@ Presolver::RuleStatus Presolver::PresolveStoreMapping(Constraint* ct, if (ct->arguments[0].values.size() == 3 && ct->arguments[1].variables[2] == ct->target_variable && ct->arguments[0].values[2] == -1 && ct->arguments[0].values[0] == 1 && - !ContainsKey(array2d_index_map_, ct->target_variable)) { + !gtl::ContainsKey(array2d_index_map_, ct->target_variable)) { array2d_index_map_[ct->target_variable] = Array2DIndexMapping( ct->arguments[1].variables[1], ct->arguments[0].values[1], ct->arguments[1].variables[0], -ct->arguments[2].Value(), ct); @@ -1848,7 +1848,7 @@ Presolver::RuleStatus Presolver::PresolveSimplifyElement(Constraint* ct, IntegerVariable* const index_var = ct->arguments[0].Var(); // Rule 2. - if (ContainsKey(affine_map_, index_var)) { + if (gtl::ContainsKey(affine_map_, index_var)) { const AffineMapping& mapping = affine_map_[index_var]; const Domain& domain = mapping.variable->domain; if (domain.is_interval && domain.values.empty()) { @@ -1905,7 +1905,7 @@ Presolver::RuleStatus Presolver::PresolveSimplifyElement(Constraint* ct, } // Rule 3. - if (ContainsKey(array2d_index_map_, index_var)) { + if (gtl::ContainsKey(array2d_index_map_, index_var)) { log->append("rewrite as a 2d element"); const Array2DIndexMapping& mapping = array2d_index_map_[index_var]; // Rewrite constraint. @@ -1966,7 +1966,7 @@ Presolver::RuleStatus Presolver::PresolveSimplifyElement(Constraint* ct, for (int64 v = std::max(1, domain.values[0]); v <= std::min(array_size, domain.values[1]); ++v) { const int64 value = array[v - 1]; - if (ContainsKey(all_values, value)) { + if (gtl::ContainsKey(all_values, value)) { to_keep.push_back(v); } else { remove_some = true; @@ -1981,7 +1981,7 @@ Presolver::RuleStatus Presolver::PresolveSimplifyElement(Constraint* ct, remove_some = true; } else { const int64 value = array[v - 1]; - if (!ContainsKey(all_values, value)) { + if (!gtl::ContainsKey(all_values, value)) { remove_some = true; } else { to_keep.push_back(v); @@ -2057,7 +2057,7 @@ Presolver::RuleStatus Presolver::PresolveSimplifyExprElement(Constraint* ct, // Rule 3. IntegerVariable* const index_var = ct->arguments[0].Var(); - if (ContainsKey(affine_map_, index_var)) { + if (gtl::ContainsKey(affine_map_, index_var)) { const AffineMapping& mapping = affine_map_[index_var]; const Domain& domain = mapping.variable->domain; if ((domain.is_interval && domain.values.empty()) || @@ -2350,8 +2350,8 @@ Presolver::RuleStatus Presolver::StoreIntEqReif(Constraint* ct, std::string* log IntegerVariable* const first = ct->arguments[0].Var(); IntegerVariable* const second = ct->arguments[1].Var(); IntegerVariable* const boolvar = ct->arguments[2].Var(); - if (ContainsKey(int_eq_reif_map_, first) && - ContainsKey(int_eq_reif_map_[first], second)) { + if (gtl::ContainsKey(int_eq_reif_map_, first) && + gtl::ContainsKey(int_eq_reif_map_[first], second)) { return NOT_CHANGED; } log->append("store eq_var info"); @@ -2371,9 +2371,9 @@ Presolver::RuleStatus Presolver::SimplifyIntNeReif(Constraint* ct, std::string* log) { if (ct->arguments[0].IsVariable() && ct->arguments[1].IsVariable() && ct->arguments[2].IsVariable() && - ContainsKey(int_eq_reif_map_, ct->arguments[0].Var()) && - ContainsKey(int_eq_reif_map_[ct->arguments[0].Var()], - ct->arguments[1].Var())) { + gtl::ContainsKey(int_eq_reif_map_, ct->arguments[0].Var()) && + gtl::ContainsKey(int_eq_reif_map_[ct->arguments[0].Var()], + ct->arguments[1].Var())) { log->append("merge constraint with opposite constraint"); IntegerVariable* const opposite_boolvar = int_eq_reif_map_[ct->arguments[0].Var()][ct->arguments[1].Var()]; @@ -2388,7 +2388,7 @@ Presolver::RuleStatus Presolver::SimplifyIntNeReif(Constraint* ct, // Store the mapping x = abs(y) for future use. Presolver::RuleStatus Presolver::StoreAbs(Constraint* ct, std::string* log) { - if (!ContainsKey(abs_map_, ct->arguments[1].Var())) { + if (!gtl::ContainsKey(abs_map_, ct->arguments[1].Var())) { // Stores abs() map. log->append("Store abs map"); abs_map_[ct->arguments[1].Var()] = ct->arguments[0].Var(); @@ -2404,7 +2404,7 @@ Presolver::RuleStatus Presolver::StoreAbs(Constraint* ct, std::string* log) { Presolver::RuleStatus Presolver::RemoveAbsFromIntLeReif(Constraint* ct, std::string* log) { if (ct->arguments[1].HasOneValue() && - ContainsKey(abs_map_, ct->arguments[0].Var())) { + gtl::ContainsKey(abs_map_, ct->arguments[0].Var())) { log->append("remove abs from constraint"); ct->arguments[0].variables[0] = abs_map_[ct->arguments[0].Var()]; const int64 value = ct->arguments[1].Value(); @@ -2428,7 +2428,7 @@ Presolver::RuleStatus Presolver::RemoveAbsFromIntLeReif(Constraint* ct, Presolver::RuleStatus Presolver::RemoveAbsFromIntEqNeReif(Constraint* ct, std::string* log) { if (ct->arguments[1].HasOneValue() && ct->arguments[1].Value() == 0 && - ContainsKey(abs_map_, ct->arguments[0].Var())) { + gtl::ContainsKey(abs_map_, ct->arguments[0].Var())) { log->append("remove abs from constraint"); ct->arguments[0].variables[0] = abs_map_[ct->arguments[0].Var()]; return CONSTRAINT_REWRITTEN; @@ -2851,7 +2851,7 @@ Presolver::RuleStatus Presolver::PresolveRegular(Constraint* ct, std::string* lo for (int time = 0; time + 1 < num_vars; ++time) { const Domain& domain = vars[time]->domain; for (const std::vector& transition : automata) { - if (!ContainsKey(reachable_states[time], transition[0])) continue; + if (!gtl::ContainsKey(reachable_states[time], transition[0])) continue; if (!domain.Contains(transition[1])) continue; reachable_states[time + 1].insert(transition[2]); } @@ -2862,9 +2862,10 @@ Presolver::RuleStatus Presolver::PresolveRegular(Constraint* ct, std::string* lo std::unordered_set new_set; const Domain& domain = vars[time]->domain; for (const std::vector& transition : automata) { - if (!ContainsKey(reachable_states[time], transition[0])) continue; + if (!gtl::ContainsKey(reachable_states[time], transition[0])) continue; if (!domain.Contains(transition[1])) continue; - if (!ContainsKey(reachable_states[time + 1], transition[2])) continue; + if (!gtl::ContainsKey(reachable_states[time + 1], transition[2])) + continue; new_set.insert(transition[0]); } reachable_states[time].swap(new_set); @@ -2876,9 +2877,10 @@ Presolver::RuleStatus Presolver::PresolveRegular(Constraint* ct, std::string* lo // Collect valid values. std::unordered_set reached_values; for (const std::vector& transition : automata) { - if (!ContainsKey(reachable_states[time], transition[0])) continue; + if (!gtl::ContainsKey(reachable_states[time], transition[0])) continue; if (!domain.Contains(transition[1])) continue; - if (!ContainsKey(reachable_states[time + 1], transition[2])) continue; + if (!gtl::ContainsKey(reachable_states[time + 1], transition[2])) + continue; reached_values.insert(transition[1]); } // Scan domain to check if we will remove values. @@ -2886,7 +2888,7 @@ Presolver::RuleStatus Presolver::PresolveRegular(Constraint* ct, std::string* lo bool remove_some = false; if (domain.is_interval) { for (int64 v = domain.values[0]; v <= domain.values[1]; ++v) { - if (ContainsKey(reached_values, v)) { + if (gtl::ContainsKey(reached_values, v)) { to_keep.push_back(v); } else { remove_some = true; @@ -2894,7 +2896,7 @@ Presolver::RuleStatus Presolver::PresolveRegular(Constraint* ct, std::string* lo } } else { for (int64 v : domain.values) { - if (ContainsKey(reached_values, v)) { + if (gtl::ContainsKey(reached_values, v)) { to_keep.push_back(v); } else { remove_some = true; @@ -3110,7 +3112,8 @@ void Presolver::MergeIntEqNe(Model* model) { } if (var != nullptr) { IntegerVariable* boolvar = ct->arguments[2].Var(); - IntegerVariable* stored = FindPtrOrNull(int_eq_reif_map[var], value); + IntegerVariable* stored = + gtl::FindPtrOrNull(int_eq_reif_map[var], value); if (stored == nullptr) { FZVLOG << "Store " << ct->DebugString() << FZENDL; int_eq_reif_map[var][value] = boolvar; @@ -3137,7 +3140,8 @@ void Presolver::MergeIntEqNe(Model* model) { } if (var != nullptr) { IntegerVariable* boolvar = ct->arguments[2].Var(); - IntegerVariable* stored = FindPtrOrNull(int_ne_reif_map[var], value); + IntegerVariable* stored = + gtl::FindPtrOrNull(int_ne_reif_map[var], value); if (stored == nullptr) { FZVLOG << "Store " << ct->DebugString() << FZENDL; int_ne_reif_map[var][value] = boolvar; @@ -3294,7 +3298,7 @@ bool Presolver::RegroupDifferent(Model* model) { const int right_index = variables_to_dense_index.IndexOrDie(right); const std::pair p = std::make_pair( std::min(left_index, right_index), std::max(left_index, right_index)); - if (ContainsKey(replace_map, p)) { + if (gtl::ContainsKey(replace_map, p)) { FZVLOG << "Apply rule RegroupDifferent on " << ct->DebugString() << FZENDL; const std::vector& rep = replace_map[p]; @@ -3307,7 +3311,7 @@ bool Presolver::RegroupDifferent(Model* model) { ct->arguments.pop_back(); new_all_diffs++; FZVLOG << " - constraint is modified to " << ct->DebugString() << FZENDL; - } else if (ContainsKey(to_kill, p)) { + } else if (gtl::ContainsKey(to_kill, p)) { ct->MarkAsInactive(); killed++; } @@ -3416,7 +3420,7 @@ bool Presolver::Run(Model* model) { if (ct->active && ct->type == "array_int_element" && ct->arguments[0].variables.size() == 1) { IntegerVariable* const index_var = ct->arguments[0].Var(); - if (ContainsKey(affine_map_, index_var)) { + if (gtl::ContainsKey(affine_map_, index_var)) { const AffineMapping& mapping = affine_map_[index_var]; if (mapping.coefficient == 1 && mapping.offset == 1) { FZVLOG << "remove offset by one from " << ct->DebugString(); @@ -3486,7 +3490,7 @@ IntegerVariable* Presolver::FindRepresentativeOfVar(IntegerVariable* var) { // First loop: find the top parent. for (;;) { IntegerVariable* parent = - FindWithDefault(var_representative_map_, var, var); + gtl::FindWithDefault(var_representative_map_, var, var); if (parent == var) break; var = parent; } @@ -3496,7 +3500,7 @@ IntegerVariable* Presolver::FindRepresentativeOfVar(IntegerVariable* var) { var_representative_map_[start_var] = var; start_var = parent; } - return FindWithDefault(var_representative_map_, var, var); + return gtl::FindWithDefault(var_representative_map_, var, var); } void Presolver::SubstituteEverywhere(Model* model) { @@ -3795,7 +3799,7 @@ void Presolver::CleanUpModelForTheCpSolver(Model* model, bool use_sat) { for (IntegerVariable* const var : ct->arguments[1].variables) { variables_in_array.insert(var); } - if (ContainsKey(variables_in_array, ct->target_variable)) { + if (gtl::ContainsKey(variables_in_array, ct->target_variable)) { FZVLOG << "Remove target variable from " << ct->DebugString() << " as it appears in the array of variables" << FZENDL; ct->RemoveTargetVariable(); diff --git a/ortools/flatzinc/reporting.cc b/ortools/flatzinc/reporting.cc index 990d54d463..5467f2903c 100644 --- a/ortools/flatzinc/reporting.cc +++ b/ortools/flatzinc/reporting.cc @@ -20,6 +20,7 @@ #include "ortools/base/logging.h" #include "ortools/base/stringprintf.h" #include "ortools/base/stringprintf.h" +#include "ortools/base/mutex.h" #include "ortools/constraint_solver/constraint_solver.h" #include "ortools/constraint_solver/constraint_solveri.h" #include "ortools/flatzinc/logging.h" @@ -191,7 +192,7 @@ MultiThreadReporting::MultiThreadReporting(bool print_all, int num_solutions, MultiThreadReporting::~MultiThreadReporting() {} void MultiThreadReporting::Init(int thread_id, const std::string& init_string) { - MutexLock lock(&mutex_); + absl::MutexLock lock(&mutex_); if (thread_id == 0) { FZLOG << init_string << FZENDL; } @@ -201,7 +202,7 @@ void MultiThreadReporting::Init(int thread_id, const std::string& init_string) { } void MultiThreadReporting::OnSearchStart(int thread_id, Type type) { - MutexLock lock(&mutex_); + absl::MutexLock lock(&mutex_); if (type_ == UNDEF) { type_ = type; if (type_ == MAXIMIZE) { @@ -214,7 +215,7 @@ void MultiThreadReporting::OnSearchStart(int thread_id, Type type) { void MultiThreadReporting::OnSatSolution(int thread_id, const std::string& solution_string) { - MutexLock lock(&mutex_); + absl::MutexLock lock(&mutex_); if (NumSolutions() < MaxNumSolutions() || ShouldPrintAllSolutions()) { if (verbose_) { LogNoLock(thread_id, "solution found"); @@ -227,7 +228,7 @@ void MultiThreadReporting::OnSatSolution(int thread_id, void MultiThreadReporting::OnOptimizeSolution(int thread_id, int64 value, const std::string& solution_string) { - MutexLock lock(&mutex_); + absl::MutexLock lock(&mutex_); if (!should_finish_) { switch (type_) { case MINIMIZE: { @@ -275,7 +276,7 @@ void MultiThreadReporting::OnOptimizeSolution(int thread_id, int64 value, } void MultiThreadReporting::Log(int thread_id, const std::string& message) const { - MutexLock lock(&mutex_); + absl::MutexLock lock(&mutex_); FZLOG << message << FZENDL; } @@ -283,12 +284,12 @@ void MultiThreadReporting::Print(int thread_id, const std::string& message) cons std::cout << message << std::endl; } bool MultiThreadReporting::ShouldFinish() const { - MutexLock lock(&mutex_); + absl::MutexLock lock(&mutex_); return should_finish_; } void MultiThreadReporting::OnSearchEnd(int thread_id, bool interrupted) { - MutexLock lock(&mutex_); + absl::MutexLock lock(&mutex_); if (verbose_) { LogNoLock(thread_id, "exiting"); } @@ -308,7 +309,7 @@ void MultiThreadReporting::OnSearchEnd(int thread_id, bool interrupted) { } int64 MultiThreadReporting::BestSolution() const { - MutexLock lock(&mutex_); + absl::MutexLock lock(&mutex_); return best_objective_; } @@ -324,7 +325,7 @@ SearchLimit* MultiThreadReporting::CreateLimit(Solver* s, int thread_id) const { } bool MultiThreadReporting::Interrupted() const { - MutexLock lock(&mutex_); + absl::MutexLock lock(&mutex_); return interrupted_; } diff --git a/ortools/flatzinc/reporting.h b/ortools/flatzinc/reporting.h index 999c9db9e2..4bb1def0d2 100644 --- a/ortools/flatzinc/reporting.h +++ b/ortools/flatzinc/reporting.h @@ -16,8 +16,8 @@ #include #include "ortools/base/integral_types.h" -#include "ortools/base/mutex.h" #include "ortools/base/stringprintf.h" +#include "ortools/base/mutex.h" #include "ortools/constraint_solver/constraint_solver.h" namespace operations_research { @@ -184,7 +184,7 @@ class MultiThreadReporting : public SearchReportingInterface { void LogNoLock(int thread_id, const std::string& message); const bool verbose_; - mutable Mutex mutex_; + mutable absl::Mutex mutex_; Type type_ GUARDED_BY(mutex_); std::string last_solution_ GUARDED_BY(mutex_); int last_thread_ GUARDED_BY(mutex_); diff --git a/ortools/flatzinc/sat_constraint.cc b/ortools/flatzinc/sat_constraint.cc index 22c3cb6201..d494b70086 100644 --- a/ortools/flatzinc/sat_constraint.cc +++ b/ortools/flatzinc/sat_constraint.cc @@ -73,7 +73,7 @@ class SatPropagator : public Constraint { CHECK(solver()->IsBooleanVar(expr, &expr_var, &expr_negated)); SATDLOG << " - SAT: Parse " << expr->DebugString() << " to " << expr_var->DebugString() << "/" << expr_negated << FZENDL; - if (ContainsKey(indices_, expr_var)) { + if (gtl::ContainsKey(indices_, expr_var)) { return sat::Literal(indices_[expr_var], !expr_negated); } const sat::BooleanVariable var = sat_.NewBooleanVariable(); diff --git a/ortools/flatzinc/solver.cc b/ortools/flatzinc/solver.cc index b22e4a650a..4854c2b62f 100644 --- a/ortools/flatzinc/solver.cc +++ b/ortools/flatzinc/solver.cc @@ -71,7 +71,7 @@ FlatzincParameters::FlatzincParameters() // ----- Solver ----- int64 Solver::SolutionValue(IntegerVariable* var) const { - IntExpr* const result = FindPtrOrNull(data_.extracted_map(), var); + IntExpr* const result = gtl::FindPtrOrNull(data_.extracted_map(), var); if (result != nullptr) { if (result->IsVar()) { return result->Var()->Value(); @@ -118,7 +118,7 @@ std::string Solver::SolutionString(const SolutionOutputSpecs& output) const { if (output.display_as_boolean) { result.append(StringPrintf(value ? "true" : "false")); } else { - StrAppend(&result, value); + absl::StrAppend(&result, value); } if (i != output.flat_variables.size() - 1) { result.append(", "); @@ -158,7 +158,7 @@ struct ConstraintsWithRequiredVariables { // Collect required variables. for (const Argument& arg : ct->arguments) { for (IntegerVariable* const var : arg.variables) { - if (var != cte->target_variable && ContainsKey(defined, var)) { + if (var != cte->target_variable && gtl::ContainsKey(defined, var)) { required.insert(var); } } @@ -284,7 +284,7 @@ bool Solver::Extract() { // TODO(user): Implement recovery mode. sorted.push_back(ctio->ct); IntegerVariable* const var = ctio->ct->target_variable; - if (var != nullptr && ContainsKey(dependencies, var)) { + if (var != nullptr && gtl::ContainsKey(dependencies, var)) { FZDLOG << " - clean " << var->DebugString() << FZENDL; for (ConstraintsWithRequiredVariables* const to_clean : dependencies[var]) { @@ -391,7 +391,7 @@ void Solver::ParseSearchAnnotations(bool ignore_unknown, for (IntegerVariable* const fz_var : fz_vars) { IntVar* const to_add = data_.Extract(fz_var)->Var(); const int occ = statistics_.NumVariableOccurrences(fz_var); - if (!ContainsKey(added, to_add) && !to_add->Bound()) { + if (!gtl::ContainsKey(added, to_add) && !to_add->Bound()) { added.insert(to_add); int_vars.push_back(to_add); occurrences.push_back(occ); @@ -458,7 +458,7 @@ void Solver::ParseSearchAnnotations(bool ignore_unknown, for (IntegerVariable* const fz_var : fz_vars) { IntVar* const to_add = data_.Extract(fz_var)->Var(); const int occ = statistics_.NumVariableOccurrences(fz_var); - if (!ContainsKey(added, to_add) && !to_add->Bound()) { + if (!gtl::ContainsKey(added, to_add) && !to_add->Bound()) { added.insert(to_add); bool_vars.push_back(to_add); occurrences.push_back(occ); @@ -490,7 +490,7 @@ void Solver::ParseSearchAnnotations(bool ignore_unknown, // Create the active_variables array, push smaller variables first. for (IntVar* const var : active_variables_) { - if (!ContainsKey(added, var) && !var->Bound()) { + if (!gtl::ContainsKey(added, var) && !var->Bound()) { if (var->Size() < 0xFFFF) { added.insert(var); active_variables->push_back(var); @@ -499,7 +499,7 @@ void Solver::ParseSearchAnnotations(bool ignore_unknown, } } for (IntVar* const var : active_variables_) { - if (!ContainsKey(added, var) && !var->Bound()) { + if (!gtl::ContainsKey(added, var) && !var->Bound()) { if (var->Size() >= 0xFFFF) { added.insert(var); active_variables->push_back(var); @@ -514,13 +514,13 @@ void Solver::ParseSearchAnnotations(bool ignore_unknown, void Solver::CollectOutputVariables(std::vector* out) { for (const SolutionOutputSpecs& output : model_.output()) { if (output.variable != nullptr) { - if (!ContainsKey(implied_variables_, output.variable)) { + if (!gtl::ContainsKey(implied_variables_, output.variable)) { out->push_back(data_.Extract(output.variable)->Var()); } } for (IntegerVariable* const var : output.flat_variables) { if (var->defining_constraint == nullptr && - !ContainsKey(implied_variables_, var)) { + !gtl::ContainsKey(implied_variables_, var)) { out->push_back(data_.Extract(var)->Var()); } } @@ -538,12 +538,12 @@ void Solver::AddCompletionDecisionBuilders( CollectOutputVariables(&output_variables); std::vector secondary_vars; for (IntVar* const var : active_variables) { - if (!ContainsKey(defined_set, var) && !var->Bound()) { + if (!gtl::ContainsKey(defined_set, var) && !var->Bound()) { secondary_vars.push_back(var); } } for (IntVar* const var : output_variables) { - if (!ContainsKey(defined_set, var) && !var->Bound()) { + if (!gtl::ContainsKey(defined_set, var) && !var->Bound()) { secondary_vars.push_back(var); } } @@ -689,7 +689,7 @@ void Solver::SyncWithModel() { for (IntegerVariable* const fz_var : model_.variables()) { if (!fz_var->active || fz_var->defining_constraint != nullptr || - ContainsKey(implied_variables_, fz_var)) { + gtl::ContainsKey(implied_variables_, fz_var)) { continue; } IntExpr* const expr = data_.Extract(fz_var); @@ -912,7 +912,8 @@ void Solver::Solve(FlatzincParameters p, SearchReportingInterface* report) { ? "**sat**" : (timeout ? "**feasible**" : "**proven**"))); const std::string obj_string = - (model_.objective() != nullptr && !no_solutions ? StrCat(best) : ""); + (model_.objective() != nullptr && !no_solutions ? absl::StrCat(best) + : ""); solver_status.append( "%% name, status, obj, solns, s_time, b_time, br, " "fails, cts, demon, delayed, mem, search\n"); diff --git a/ortools/flatzinc/solver_data.cc b/ortools/flatzinc/solver_data.cc index d079a91bc3..4c58334bff 100644 --- a/ortools/flatzinc/solver_data.cc +++ b/ortools/flatzinc/solver_data.cc @@ -55,7 +55,7 @@ std::vector SolverData::GetOrCreateVariableArray(const Argument& arg) { } IntExpr* SolverData::Extract(IntegerVariable* var) { - IntExpr* result = FindPtrOrNull(extracted_map_, var); + IntExpr* result = gtl::FindPtrOrNull(extracted_map_, var); if (result != nullptr) { return result; } @@ -96,7 +96,7 @@ void SolverData::StoreAllDifferent(std::vector diffs) { bool SolverData::IsAllDifferent(std::vector diffs) const { std::sort(diffs.begin(), diffs.end()); - return ContainsKey(alldiffs_, diffs); + return gtl::ContainsKey(alldiffs_, diffs); } void SolverData::CreateSatPropagatorAndAddToSolver() { diff --git a/ortools/flatzinc/solver_util.cc b/ortools/flatzinc/solver_util.cc index 9511ec98d4..4c8b8efea7 100644 --- a/ortools/flatzinc/solver_util.cc +++ b/ortools/flatzinc/solver_util.cc @@ -195,7 +195,7 @@ std::string MemoryUsage() { } else if (memory_usage > kDisplayThreshold * kKiloByte) { return StringPrintf("%2lf KB", memory_usage * 1.0 / kKiloByte); } else { - return StrCat(memory_usage); + return absl::StrCat(memory_usage); } } diff --git a/ortools/glop/basis_representation.cc b/ortools/glop/basis_representation.cc index bf76bfef33..d81f74855c 100644 --- a/ortools/glop/basis_representation.cc +++ b/ortools/glop/basis_representation.cc @@ -139,7 +139,7 @@ EtaFactorization::EtaFactorization() : eta_matrix_() {} EtaFactorization::~EtaFactorization() { Clear(); } -void EtaFactorization::Clear() { STLDeleteElements(&eta_matrix_); } +void EtaFactorization::Clear() { gtl::STLDeleteElements(&eta_matrix_); } void EtaFactorization::Update(ColIndex entering_col, RowIndex leaving_variable_row, diff --git a/ortools/glop/lp_solver.cc b/ortools/glop/lp_solver.cc index 248a9502a7..5a0ca279b8 100644 --- a/ortools/glop/lp_solver.cc +++ b/ortools/glop/lp_solver.cc @@ -89,7 +89,7 @@ void DumpLinearProgramIfRequiredByFlags(const LinearProgram& linear_program, const int file_num = FLAGS_lp_dump_file_number >= 0 ? FLAGS_lp_dump_file_number : num; StringAppendF(&filename, "-%06d.pb", file_num); - const std::string filespec = StrCat(FLAGS_lp_dump_dir, "/", filename); + const std::string filespec = absl::StrCat(FLAGS_lp_dump_dir, "/", filename); MPModelProto proto; LinearProgramToMPModelProto(linear_program, &proto); const ProtoWriteFormat write_format = FLAGS_lp_dump_binary_file diff --git a/ortools/glop/preprocessor.cc b/ortools/glop/preprocessor.cc index 1f1d904d5a..875ebe7ca2 100644 --- a/ortools/glop/preprocessor.cc +++ b/ortools/glop/preprocessor.cc @@ -14,9 +14,11 @@ #include "ortools/glop/preprocessor.h" +#include "ortools/base/stringprintf.h" #include "ortools/base/stringprintf.h" #include "ortools/glop/revised_simplex.h" #include "ortools/glop/status.h" +#include "ortools/lp_data/lp_data_utils.h" #include "ortools/lp_data/lp_utils.h" #include "ortools/lp_data/matrix_utils.h" @@ -144,7 +146,7 @@ void MainLpPreprocessor::RunAndPushIfRelevant( if (preprocessor->Run(lp)) { const EntryIndex new_num_entries = lp->num_entries(); const double preprocess_time = time_limit->GetElapsedTime() - start_time; - VLOG(1) << StringPrintf( + VLOG(1) << absl::StrFormat( "%s(%fs): %d(%d) rows, %d(%d) columns, %lld(%lld) entries.", name.c_str(), preprocess_time, lp->num_constraints().value(), (lp->num_constraints() - initial_num_rows_).value(), diff --git a/ortools/graph/bellman_ford.cc b/ortools/graph/bellman_ford.cc index 5dc506d460..c551270eb9 100644 --- a/ortools/graph/bellman_ford.cc +++ b/ortools/graph/bellman_ford.cc @@ -14,6 +14,7 @@ #include #include +#include #include #include "ortools/base/integral_types.h" diff --git a/ortools/graph/connected_components.h b/ortools/graph/connected_components.h index 22cf863480..c473279f71 100644 --- a/ortools/graph/connected_components.h +++ b/ortools/graph/connected_components.h @@ -182,15 +182,15 @@ class ConnectedComponentsFinder { // Returns true iff both nodes are in the same connected component. // Returns false if either node has not been already added with AddNode. bool Connected(T node1, T node2) { - return delegate_.Connected(FindWithDefault(index_, node1, -1), - FindWithDefault(index_, node2, -1)); + return delegate_.Connected(gtl::FindWithDefault(index_, node1, -1), + gtl::FindWithDefault(index_, node2, -1)); } // Finds the connected component containing a node, and returns the // total number of nodes in that component. Returns zero iff the // node has not been already added with AddNode. int GetSize(T node) { - return delegate_.GetSize(FindWithDefault(index_, node, -1)); + return delegate_.GetSize(gtl::FindWithDefault(index_, node, -1)); } // Finds all the connected components and assigns them to components. diff --git a/ortools/graph/ebert_graph.h b/ortools/graph/ebert_graph.h index 561a78b32b..d1c8553318 100644 --- a/ortools/graph/ebert_graph.h +++ b/ortools/graph/ebert_graph.h @@ -305,7 +305,7 @@ class StarGraphBase { if (node == kNilNode) { return "NilNode"; } else { - return StrCat(static_cast(node)); + return absl::StrCat(static_cast(node)); } } @@ -313,7 +313,7 @@ class StarGraphBase { if (arc == kNilArc) { return "NilArc"; } else { - return StrCat(static_cast(arc)); + return absl::StrCat(static_cast(arc)); } } diff --git a/ortools/graph/io.h b/ortools/graph/io.h index fe9a473007..6bb6f00b81 100644 --- a/ortools/graph/io.h +++ b/ortools/graph/io.h @@ -141,7 +141,8 @@ util::StatusOr ReadGraphFile( ++num_lines_read; if (num_lines_read == 1) { std::vector header_ints; - if (!SplitStringAndParse(line, " ", &safe_strto64, &header_ints) || + if (!SplitStringAndParse(line, " ", &strings::safe_strto64, + &header_ints) || header_ints.size() < 2 || header_ints[0] < 0 || header_ints[1] < 0) { return util::Status( util::error::INVALID_ARGUMENT, diff --git a/ortools/graph/linear_assignment.h b/ortools/graph/linear_assignment.h index 2c7ede54bf..23ea65619a 100644 --- a/ortools/graph/linear_assignment.h +++ b/ortools/graph/linear_assignment.h @@ -1447,7 +1447,7 @@ void LinearSumAssignment::ReportAndAccumulateStats() { template bool LinearSumAssignment::ComputeAssignment() { - CHECK_NOTNULL(graph_); + CHECK(graph_ != nullptr); bool ok = graph_->num_nodes() == 2 * num_left_nodes_; if (!ok) return false; // Note: FinalizeSetup() might have been called already by white-box diff --git a/ortools/graph/shortestpaths.cc b/ortools/graph/shortestpaths.cc index 65a60a1f39..22aabfc1d0 100644 --- a/ortools/graph/shortestpaths.cc +++ b/ortools/graph/shortestpaths.cc @@ -21,7 +21,6 @@ #include #include -#include "ortools/base/casts.h" #include "ortools/base/commandlineflags.h" #include "ortools/base/integral_types.h" #include "ortools/base/logging.h" diff --git a/ortools/graph/util.h b/ortools/graph/util.h index 666dda6820..8624e6bfcb 100644 --- a/ortools/graph/util.h +++ b/ortools/graph/util.h @@ -308,7 +308,7 @@ void RemoveCyclesFromPath(const Graph& graph, std::vector* arc_path) { int node = graph.Tail(arc_path->front()); int new_size = 0; while (new_size < arc_path->size()) { // To prevent cycle on bad input. - const int arc = FindOrDie(last_arc_leaving_node, node); + const int arc = gtl::FindOrDie(last_arc_leaving_node, node); if (arc == -1) break; (*arc_path)[new_size++] = arc; node = graph.Head(arc); @@ -322,7 +322,7 @@ bool PathHasCycle(const Graph& graph, const std::vector& arc_path) { std::set seen; seen.insert(graph.Tail(arc_path.front())); for (const int arc : arc_path) { - if (!InsertIfNotPresent(&seen, graph.Head(arc))) return true; + if (!gtl::InsertIfNotPresent(&seen, graph.Head(arc))) return true; } return false; } diff --git a/ortools/linear_solver/bop_interface.cc b/ortools/linear_solver/bop_interface.cc index 9b80625b27..c13870bf42 100644 --- a/ortools/linear_solver/bop_interface.cc +++ b/ortools/linear_solver/bop_interface.cc @@ -303,8 +303,7 @@ void BopInterface::ExtractNewVariables() { const glop::ColIndex num_cols(solver_->variables_.size()); for (glop::ColIndex col(last_variable_index_); col < num_cols; ++col) { MPVariable* const var = solver_->variables_[col.value()]; - const glop::ColIndex new_col = - linear_program_.FindOrCreateVariable(var->name()); + const glop::ColIndex new_col = linear_program_.CreateNewVariable(); DCHECK_EQ(new_col, col); set_variable_as_extracted(col.value(), true); linear_program_.SetVariableBounds(col, var->lb(), var->ub()); @@ -326,8 +325,7 @@ void BopInterface::ExtractNewConstraints() { const double lb = ct->lb(); const double ub = ct->ub(); - const glop::RowIndex new_row = - linear_program_.FindOrCreateConstraint(ct->name()); + const glop::RowIndex new_row = linear_program_.CreateNewConstraint(); DCHECK_EQ(new_row, row); linear_program_.SetConstraintBounds(row, lb, ub); diff --git a/ortools/linear_solver/cbc_interface.cc b/ortools/linear_solver/cbc_interface.cc index 219d1de8fa..d851a6b6e3 100644 --- a/ortools/linear_solver/cbc_interface.cc +++ b/ortools/linear_solver/cbc_interface.cc @@ -238,6 +238,16 @@ void CBCInterface::AddVariable(MPVariable* const var) { // Solve the LP/MIP. Returns true only if the optimal solution was revealed. // Returns the status of the search. MPSolver::ResultStatus CBCInterface::Solve(const MPSolverParameters& param) { + // CBC requires unique variable and constraint names. By using Lookup*, we + // generate variable and constraint indices and ensure the duplicate name + // crash will happen here with a readable error message. + if (!solver_->variables_.empty()) { + solver_->LookupVariableOrNull(solver_->variables_[0]->name()); + } + if (!solver_->constraints_.empty()) { + solver_->LookupConstraintOrNull(solver_->constraints_[0]->name()); + } + WallTimer timer; timer.Start(); diff --git a/ortools/linear_solver/glop_interface.cc b/ortools/linear_solver/glop_interface.cc index bbbd6e6f1e..f80628ad48 100644 --- a/ortools/linear_solver/glop_interface.cc +++ b/ortools/linear_solver/glop_interface.cc @@ -286,8 +286,7 @@ void GLOPInterface::ExtractNewVariables() { const glop::ColIndex num_cols(solver_->variables_.size()); for (glop::ColIndex col(last_variable_index_); col < num_cols; ++col) { MPVariable* const var = solver_->variables_[col.value()]; - const glop::ColIndex new_col = - linear_program_.FindOrCreateVariable(var->name()); + const glop::ColIndex new_col = linear_program_.CreateNewVariable(); DCHECK_EQ(new_col, col); set_variable_as_extracted(col.value(), true); linear_program_.SetVariableBounds(col, var->lb(), var->ub()); @@ -304,8 +303,7 @@ void GLOPInterface::ExtractNewConstraints() { const double lb = ct->lb(); const double ub = ct->ub(); - const glop::RowIndex new_row = - linear_program_.FindOrCreateConstraint(ct->name()); + const glop::RowIndex new_row = linear_program_.CreateNewConstraint(); DCHECK_EQ(new_row, row); linear_program_.SetConstraintBounds(row, lb, ub); diff --git a/ortools/linear_solver/linear_solver.cc b/ortools/linear_solver/linear_solver.cc index fea05cde07..7b4aab6f0e 100644 --- a/ortools/linear_solver/linear_solver.cc +++ b/ortools/linear_solver/linear_solver.cc @@ -72,7 +72,7 @@ namespace operations_research { double MPConstraint::GetCoefficient(const MPVariable* const var) const { DLOG_IF(DFATAL, !interface_->solver_->OwnsVariable(var)) << var; if (var == nullptr) return 0.0; - return FindWithDefault(coefficients_, var, 0.0); + return gtl::FindWithDefault(coefficients_, var, 0.0); } void MPConstraint::SetCoefficient(const MPVariable* const var, double coeff) { @@ -154,7 +154,7 @@ bool MPConstraint::ContainsNewVariables() { double MPObjective::GetCoefficient(const MPVariable* const var) const { DLOG_IF(DFATAL, !interface_->solver_->OwnsVariable(var)) << var; if (var == nullptr) return 0.0; - return FindWithDefault(coefficients_, var, 0.0); + return gtl::FindWithDefault(coefficients_, var, 0.0); } void MPObjective::SetCoefficient(const MPVariable* const var, double coeff) { @@ -739,7 +739,7 @@ void MPSolver::ExportModelToProto(MPModelProto* output_model) const { std::vector > linear_term; for (CoeffEntry entry : constraint->coefficients_) { const MPVariable* const var = entry.first; - const int var_index = FindWithDefault(var_to_index, var, -1); + const int var_index = gtl::FindWithDefault(var_to_index, var, -1); DCHECK_NE(-1, var_index); const double coeff = entry.second; linear_term.push_back(std::pair(var_index, coeff)); @@ -821,8 +821,8 @@ util::Status MPSolver::LoadSolutionFromProto( void MPSolver::Clear() { MutableObjective()->Clear(); - STLDeleteElements(&variables_); - STLDeleteElements(&constraints_); + gtl::STLDeleteElements(&variables_); + gtl::STLDeleteElements(&constraints_); variables_.clear(); variable_name_to_index_.clear(); variable_is_extracted_.clear(); @@ -850,7 +850,7 @@ MPVariable* MPSolver::MakeVar(double lb, double ub, bool integer, const int var_index = NumVariables(); const std::string fixed_name = name.empty() ? StringPrintf("auto_v_%09d", var_index) : name; - InsertOrDie(&variable_name_to_index_, fixed_name, var_index); + gtl::InsertOrDie(&variable_name_to_index_, fixed_name, var_index); MPVariable* v = new MPVariable(var_index, lb, ub, integer, fixed_name, interface_.get()); variables_.push_back(v); @@ -916,7 +916,8 @@ MPConstraint* MPSolver::MakeRowConstraint(double lb, double ub, const std::string fixed_name = name.empty() ? StringPrintf("auto_c_%09d", constraint_index) : name; if (constraint_name_to_index_) { - InsertOrDie(constraint_name_to_index_.get(), fixed_name, constraint_index); + gtl::InsertOrDie(&*constraint_name_to_index_, fixed_name, + constraint_index); } MPConstraint* const constraint = new MPConstraint(constraint_index, lb, ub, fixed_name, interface_.get()); @@ -1246,13 +1247,11 @@ double MPSolver::ComputeExactConditionNumber() const { bool MPSolver::OwnsVariable(const MPVariable* var) const { if (var == nullptr) return false; - // First, verify that a variable with the same name exists, and look up - // its index (names are unique, so there can be only one). - const int var_index = - FindWithDefault(variable_name_to_index_, var->name(), -1); - if (var_index == -1) return false; - // Then, verify that the variable with this index has the same address. - return variables_[var_index] == var; + if (var->index() >= 0 && var->index() < variables_.size()) { + // Then, verify that the variable with this index has the same address. + return variables_[var->index()] == var; + } + return false; } bool MPSolver::ExportModelAsLpFormat(bool obfuscate, std::string* model_str) const { diff --git a/ortools/linear_solver/model_exporter.cc b/ortools/linear_solver/model_exporter.cc index 342db34bc7..a2ce66ca3e 100644 --- a/ortools/linear_solver/model_exporter.cc +++ b/ortools/linear_solver/model_exporter.cc @@ -66,7 +66,7 @@ std::string NameManager::MakeUniqueName(const std::string& name) { // Find the 'n' so that "name_n" does not already exist. int n = last_n_; while (!names_set_.insert(result).second) { - result = StrCat(name, "_", n); + result = absl::StrCat(name, "_", n); ++n; } // We keep the last n used to avoid a quadratic behavior in case @@ -79,7 +79,8 @@ std::string MakeExportableName(const std::string& name, bool* found_forbidden_ch // Prepend with "_" all the names starting with a forbidden character. const std::string kForbiddenFirstChars = "$.0123456789"; *found_forbidden_char = kForbiddenFirstChars.find(name[0]) != std::string::npos; - std::string exportable_name = *found_forbidden_char ? StrCat("_", name) : name; + std::string exportable_name = + *found_forbidden_char ? absl::StrCat("_", name) : name; // Replace all the other forbidden characters with "_". const std::string kForbiddenChars = " +-*/<>=:\\"; @@ -100,7 +101,7 @@ std::vector MPModelProtoExporter::ExtractAndProcessNames( const int num_items = proto.size(); std::vector result(num_items); NameManager namer; - const int num_digits = StrCat(num_items).size(); + const int num_digits = absl::StrCat(num_items).size(); int i = 0; for (const auto& item : proto) { const std::string obfuscated_name = @@ -200,16 +201,18 @@ void LineBreaker::Append(const std::string& s) { line_size_ += s.size(); if (line_size_ > max_line_size_) { line_size_ = s.size(); - StrAppend(&output_, "\n "); + absl::StrAppend(&output_, "\n "); } - StrAppend(&output_, s); + absl::StrAppend(&output_, s); } std::string DoubleToStringWithForcedSign(double d) { - return StrCat((d < 0 ? "" : "+"), absl::LegacyPrecision(d)); + return absl::StrCat((d < 0 ? "" : "+"), absl::LegacyPrecision(d)); } -std::string DoubleToString(double d) { return StrCat(absl::LegacyPrecision(d)); } +std::string DoubleToString(double d) { + return absl::StrCat(absl::LegacyPrecision(d)); +} } // namespace @@ -221,8 +224,8 @@ bool MPModelProtoExporter::WriteLpTerm(int var_index, double coefficient, return false; } if (coefficient != 0.0) { - *output = StrCat(DoubleToStringWithForcedSign(coefficient), " ", - exported_variable_names_[var_index], " "); + *output = absl::StrCat(DoubleToStringWithForcedSign(coefficient), " ", + exported_variable_names_[var_index], " "); } return true; } @@ -263,11 +266,11 @@ bool MPModelProtoExporter::ExportModelAsLpFormat(bool obfuscated, AppendComments("\\", output); // Objective - StrAppend(output, proto_.maximize() ? "Maximize\n" : "Minimize\n"); + absl::StrAppend(output, proto_.maximize() ? "Maximize\n" : "Minimize\n"); LineBreaker obj_line_breaker(FLAGS_lp_max_line_length); obj_line_breaker.Append(" Obj: "); if (proto_.objective_offset() != 0.0) { - obj_line_breaker.Append(StrCat( + obj_line_breaker.Append(absl::StrCat( DoubleToStringWithForcedSign(proto_.objective_offset()), " Constant ")); } std::vector show_variable(proto_.variable_size(), @@ -282,7 +285,7 @@ bool MPModelProtoExporter::ExportModelAsLpFormat(bool obfuscated, show_variable[var_index] = coeff != 0.0 || FLAGS_lp_shows_unused_variables; } // Constraints - StrAppend(output, obj_line_breaker.GetOutput(), "\nSubject to\n"); + absl::StrAppend(output, obj_line_breaker.GetOutput(), "\nSubject to\n"); for (int cst_index = 0; cst_index < proto_.constraint_size(); ++cst_index) { const MPConstraintProto& ct_proto = proto_.constraint(cst_index); const std::string& name = exported_constraint_names_[cst_index]; @@ -305,38 +308,38 @@ bool MPModelProtoExporter::ExportModelAsLpFormat(bool obfuscated, const double lb = ct_proto.lower_bound(); const double ub = ct_proto.upper_bound(); if (lb == ub) { - line_breaker.Append(StrCat(" = ", DoubleToString(ub), "\n")); - StrAppend(output, " ", name, ": ", line_breaker.GetOutput()); + line_breaker.Append(absl::StrCat(" = ", DoubleToString(ub), "\n")); + absl::StrAppend(output, " ", name, ": ", line_breaker.GetOutput()); } else { if (ub != +std::numeric_limits::infinity()) { std::string rhs_name = name; if (lb != -std::numeric_limits::infinity()) { - StrAppend(&rhs_name, "_rhs"); + absl::StrAppend(&rhs_name, "_rhs"); } - StrAppend(output, " ", rhs_name, ": ", line_breaker.GetOutput()); - const std::string relation = StrCat(" <= ", DoubleToString(ub), "\n"); + absl::StrAppend(output, " ", rhs_name, ": ", line_breaker.GetOutput()); + const std::string relation = absl::StrCat(" <= ", DoubleToString(ub), "\n"); // Here we have to make sure we do not add the relation to the contents // of line_breaker, which may be used in the subsequent clause. - if (!line_breaker.WillFit(relation)) StrAppend(output, "\n "); - StrAppend(output, relation); + if (!line_breaker.WillFit(relation)) absl::StrAppend(output, "\n "); + absl::StrAppend(output, relation); } if (lb != -std::numeric_limits::infinity()) { std::string lhs_name = name; if (ub != +std::numeric_limits::infinity()) { - StrAppend(&lhs_name, "_lhs"); + absl::StrAppend(&lhs_name, "_lhs"); } - StrAppend(output, " ", lhs_name, ": ", line_breaker.GetOutput()); - const std::string relation = StrCat(" >= ", DoubleToString(lb), "\n"); - if (!line_breaker.WillFit(relation)) StrAppend(output, "\n "); - StrAppend(output, relation); + absl::StrAppend(output, " ", lhs_name, ": ", line_breaker.GetOutput()); + const std::string relation = absl::StrCat(" >= ", DoubleToString(lb), "\n"); + if (!line_breaker.WillFit(relation)) absl::StrAppend(output, "\n "); + absl::StrAppend(output, relation); } } } // Bounds - StrAppend(output, "Bounds\n"); + absl::StrAppend(output, "Bounds\n"); if (proto_.objective_offset() != 0.0) { - StrAppend(output, " 1 <= Constant <= 1\n"); + absl::StrAppend(output, " 1 <= Constant <= 1\n"); } for (int var_index = 0; var_index < proto_.variable_size(); ++var_index) { if (!show_variable[var_index]) continue; @@ -348,19 +351,19 @@ bool MPModelProtoExporter::ExportModelAsLpFormat(bool obfuscated, exported_variable_names_[var_index].c_str(), ub); } else { if (lb != -std::numeric_limits::infinity()) { - StrAppend(output, " ", DoubleToString(lb), " <= "); + absl::StrAppend(output, " ", DoubleToString(lb), " <= "); } - StrAppend(output, exported_variable_names_[var_index]); + absl::StrAppend(output, exported_variable_names_[var_index]); if (ub != std::numeric_limits::infinity()) { - StrAppend(output, " <= ", DoubleToString(ub)); + absl::StrAppend(output, " <= ", DoubleToString(ub)); } - StrAppend(output, "\n"); + absl::StrAppend(output, "\n"); } } // Binaries if (num_binary_variables_ > 0) { - StrAppend(output, "Binaries\n"); + absl::StrAppend(output, "Binaries\n"); for (int var_index = 0; var_index < proto_.variable_size(); ++var_index) { if (!show_variable[var_index]) continue; const MPVariableProto& var_proto = proto_.variable(var_index); @@ -373,16 +376,16 @@ bool MPModelProtoExporter::ExportModelAsLpFormat(bool obfuscated, // Generals if (num_integer_variables_ > 0) { - StrAppend(output, "Generals\n"); + absl::StrAppend(output, "Generals\n"); for (int var_index = 0; var_index < proto_.variable_size(); ++var_index) { if (!show_variable[var_index]) continue; const MPVariableProto& var_proto = proto_.variable(var_index); if (var_proto.is_integer() && !IsBoolean(var_proto)) { - StrAppend(output, " ", exported_variable_names_[var_index], "\n"); + absl::StrAppend(output, " ", exported_variable_names_[var_index], "\n"); } } } - StrAppend(output, "End\n"); + absl::StrAppend(output, "End\n"); return true; } @@ -415,7 +418,7 @@ void MPModelProtoExporter::AppendMpsLineHeader(const std::string& id, void MPModelProtoExporter::AppendMpsLineHeaderWithNewLine( const std::string& id, const std::string& name, std::string* output) const { AppendMpsLineHeader(id, name, output); - StrAppend(output, "\n"); + absl::StrAppend(output, "\n"); } void MPModelProtoExporter::AppendMpsTermWithContext(const std::string& head_name, @@ -434,13 +437,13 @@ void MPModelProtoExporter::AppendMpsBound(const std::string& bound_type, std::string* output) const { AppendMpsLineHeader(bound_type, "BOUND", output); AppendMpsPair(name, value, output); - StrAppend(output, "\n"); + absl::StrAppend(output, "\n"); } void MPModelProtoExporter::AppendNewLineIfTwoColumns(std::string* output) { ++current_mps_column_; if (current_mps_column_ == 2) { - StrAppend(output, "\n"); + absl::StrAppend(output, "\n"); current_mps_column_ = 0; } } @@ -511,7 +514,7 @@ bool MPModelProtoExporter::ExportModelAsMpsFormat(bool fixed_format, } } if (!rows_section.empty()) { - StrAppend(output, "ROWS\n", rows_section); + absl::StrAppend(output, "ROWS\n", rows_section); } // As the information regarding a column needs to be contiguous, we create @@ -548,7 +551,7 @@ bool MPModelProtoExporter::ExportModelAsMpsFormat(bool fixed_format, } AppendMpsColumns(/*integrality=*/false, transpose, &columns_section); if (!columns_section.empty()) { - StrAppend(output, "COLUMNS\n", columns_section); + absl::StrAppend(output, "COLUMNS\n", columns_section); } // RHS (right-hand-side) section. @@ -567,7 +570,7 @@ bool MPModelProtoExporter::ExportModelAsMpsFormat(bool fixed_format, } AppendNewLineIfTwoColumns(&rhs_section); if (!rhs_section.empty()) { - StrAppend(output, "RHS\n", rhs_section); + absl::StrAppend(output, "RHS\n", rhs_section); } // RANGES section. @@ -583,7 +586,7 @@ bool MPModelProtoExporter::ExportModelAsMpsFormat(bool fixed_format, } AppendNewLineIfTwoColumns(&ranges_section); if (!ranges_section.empty()) { - StrAppend(output, "RANGES\n", ranges_section); + absl::StrAppend(output, "RANGES\n", ranges_section); } // BOUNDS section. @@ -627,10 +630,10 @@ bool MPModelProtoExporter::ExportModelAsMpsFormat(bool fixed_format, } } if (!bounds_section.empty()) { - StrAppend(output, "BOUNDS\n", bounds_section); + absl::StrAppend(output, "BOUNDS\n", bounds_section); } - StrAppend(output, "ENDATA\n"); + absl::StrAppend(output, "ENDATA\n"); return true; } diff --git a/ortools/linear_solver/model_validator.cc b/ortools/linear_solver/model_validator.cc index 53eb06c5ca..40cbe950fc 100644 --- a/ortools/linear_solver/model_validator.cc +++ b/ortools/linear_solver/model_validator.cc @@ -32,20 +32,21 @@ std::string FindErrorInMPVariable(const MPVariableProto& variable) { variable.lower_bound() == kInfinity || variable.upper_bound() == -kInfinity || variable.lower_bound() > variable.upper_bound()) { - return StrCat("Infeasible bounds: [", - absl::LegacyPrecision(variable.lower_bound()), ", ", - absl::LegacyPrecision(variable.upper_bound()), "]"); + return absl::StrCat("Infeasible bounds: [", + absl::LegacyPrecision(variable.lower_bound()), ", ", + absl::LegacyPrecision(variable.upper_bound()), "]"); } if (variable.is_integer() && ceil(variable.lower_bound()) > floor(variable.upper_bound())) { - return StrCat("Infeasible bounds for integer variable: [", - absl::LegacyPrecision(variable.lower_bound()), ", ", - absl::LegacyPrecision(variable.upper_bound()), "]", - " translate to the empty set"); + return absl::StrCat("Infeasible bounds for integer variable: [", + absl::LegacyPrecision(variable.lower_bound()), ", ", + absl::LegacyPrecision(variable.upper_bound()), "]", + " translate to the empty set"); } if (!std::isfinite(variable.objective_coefficient())) { - return StrCat("Invalid objective_coefficient: ", - absl::LegacyPrecision(variable.objective_coefficient())); + return absl::StrCat( + "Invalid objective_coefficient: ", + absl::LegacyPrecision(variable.objective_coefficient())); } return std::string(); } @@ -60,9 +61,9 @@ std::string FindErrorInMPConstraint(const MPConstraintProto& constraint, constraint.lower_bound() == kInfinity || constraint.upper_bound() == -kInfinity || constraint.lower_bound() > constraint.upper_bound()) { - return StrCat("Infeasible bounds: [", - absl::LegacyPrecision(constraint.lower_bound()), ", ", - absl::LegacyPrecision(constraint.upper_bound()), "]"); + return absl::StrCat("Infeasible bounds: [", + absl::LegacyPrecision(constraint.lower_bound()), ", ", + absl::LegacyPrecision(constraint.upper_bound()), "]"); } // TODO(user): clarify explicitly, at least in a comment, whether we want @@ -72,18 +73,19 @@ std::string FindErrorInMPConstraint(const MPConstraintProto& constraint, const int num_vars_in_ct = constraint.var_index_size(); const int num_coeffs_in_ct = constraint.coefficient_size(); if (num_vars_in_ct != num_coeffs_in_ct) { - return StrCat("var_index_size() != coefficient_size() (", num_vars_in_ct, - " VS ", num_coeffs_in_ct); + return absl::StrCat("var_index_size() != coefficient_size() (", + num_vars_in_ct, " VS ", num_coeffs_in_ct); } for (int i = 0; i < num_vars_in_ct; ++i) { const int var_index = constraint.var_index(i); if (var_index >= num_vars_in_model || var_index < 0) { - return StrCat("var_index(", i, ")=", var_index, " is out of bounds"); + return absl::StrCat("var_index(", i, ")=", var_index, + " is out of bounds"); } const double coeff = constraint.coefficient(i); if (!std::isfinite(coeff)) { - return StrCat("coefficient(", i, ")=", absl::LegacyPrecision(coeff), - " is invalid"); + return absl::StrCat("coefficient(", i, ")=", absl::LegacyPrecision(coeff), + " is invalid"); } } @@ -98,7 +100,8 @@ std::string FindErrorInMPConstraint(const MPConstraintProto& constraint, (*var_mask)[var_index] = false; } if (duplicate_var_index >= 0) { - return StrCat("var_index #", duplicate_var_index, " appears several times"); + return absl::StrCat("var_index #", duplicate_var_index, + " appears several times"); } // We found no error, all is fine. @@ -108,25 +111,25 @@ std::string FindErrorInMPConstraint(const MPConstraintProto& constraint, std::string FindErrorInSolutionHint(const PartialVariableAssignment& solution_hint, int num_vars) { if (solution_hint.var_index_size() != solution_hint.var_value_size()) { - return StrCat("var_index_size() != var_value_size() [", - solution_hint.var_index_size(), " VS ", - solution_hint.var_value_size()); + return absl::StrCat("var_index_size() != var_value_size() [", + solution_hint.var_index_size(), " VS ", + solution_hint.var_value_size()); } std::vector var_in_hint(num_vars, false); for (int i = 0; i < solution_hint.var_index_size(); ++i) { const int var_index = solution_hint.var_index(i); if (var_index >= num_vars || var_index < 0) { - return StrCat("var_index(", i, ")=", var_index, " is invalid.", - " It must be in [0, ", num_vars, ")"); + return absl::StrCat("var_index(", i, ")=", var_index, " is invalid.", + " It must be in [0, ", num_vars, ")"); } if (var_in_hint[var_index]) { - return StrCat("Duplicate var_index = ", var_index); + return absl::StrCat("Duplicate var_index = ", var_index); } var_in_hint[var_index] = true; if (!std::isfinite(solution_hint.var_value(i))) { - return StrCat("var_value(", i, - ")=", absl::LegacyPrecision(solution_hint.var_value(i)), - " is not a finite number"); + return absl::StrCat("var_value(", i, ")=", + absl::LegacyPrecision(solution_hint.var_value(i)), + " is not a finite number"); } } return std::string(); @@ -142,8 +145,8 @@ std::string FindErrorInMPModelProto(const MPModelProto& model) { // accept models without variables and/or constraints. if (!std::isfinite(model.objective_offset())) { - return StrCat("Invalid objective_offset: ", - absl::LegacyPrecision(model.objective_offset())); + return absl::StrCat("Invalid objective_offset: ", + absl::LegacyPrecision(model.objective_offset())); } const int num_vars = model.variable_size(); const int num_cts = model.constraint_size(); @@ -153,8 +156,8 @@ std::string FindErrorInMPModelProto(const MPModelProto& model) { for (int i = 0; i < num_vars; ++i) { error = FindErrorInMPVariable(model.variable(i)); if (!error.empty()) { - return StrCat("In variable #", i, ": ", error, ". Variable proto: ", - ProtobufShortDebugString(model.variable(i))); + return absl::StrCat("In variable #", i, ": ", error, ". Variable proto: ", + ProtobufShortDebugString(model.variable(i))); } } @@ -171,24 +174,26 @@ std::string FindErrorInMPModelProto(const MPModelProto& model) { if (constraint.var_index_size() > kMaxNumVarsInPrintedConstraint) { constraint_light.mutable_var_index()->Truncate( kMaxNumVarsInPrintedConstraint); - StrAppend(&suffix_str, " (var_index cropped; size=", - constraint.var_index_size(), ")."); + absl::StrAppend(&suffix_str, " (var_index cropped; size=", + constraint.var_index_size(), ")."); } if (constraint.coefficient_size() > kMaxNumVarsInPrintedConstraint) { constraint_light.mutable_coefficient()->Truncate( kMaxNumVarsInPrintedConstraint); - StrAppend(&suffix_str, " (coefficient cropped; size=", - constraint.coefficient_size(), ")."); + absl::StrAppend(&suffix_str, " (coefficient cropped; size=", + constraint.coefficient_size(), ")."); } - return StrCat("In constraint #", i, ": ", error, ". Constraint proto: ", - ProtobufShortDebugString(constraint_light), suffix_str); + return absl::StrCat( + "In constraint #", i, ": ", error, + ". Constraint proto: ", ProtobufShortDebugString(constraint_light), + suffix_str); } } // Validate the solution hint. error = FindErrorInSolutionHint(model.solution_hint(), num_vars); if (!error.empty()) { - return StrCat("In solution_hint(): ", error); + return absl::StrCat("In solution_hint(): ", error); } return std::string(); @@ -202,7 +207,7 @@ std::string FindFeasibilityErrorInSolutionHint(const MPModelProto& model, // First, we validate the solution hint. std::string error = FindErrorInSolutionHint(model.solution_hint(), num_vars); - if (!error.empty()) return StrCat("Invalid solution_hint: ", error); + if (!error.empty()) return absl::StrCat("Invalid solution_hint: ", error); // Special error message for the empty case. if (num_vars > 0 && model.solution_hint().var_index_size() == 0) { @@ -211,9 +216,9 @@ std::string FindFeasibilityErrorInSolutionHint(const MPModelProto& model, // To be feasible, the hint must not be partial. if (model.solution_hint().var_index_size() != num_vars) { - return StrCat("Partial solution_hint: only ", - model.solution_hint().var_index_size(), " out of the ", - num_vars, " problem variables are set."); + return absl::StrCat("Partial solution_hint: only ", + model.solution_hint().var_index_size(), " out of the ", + num_vars, " problem variables are set."); } // All the values must be exactly in the variable bounds. @@ -226,12 +231,12 @@ std::string FindFeasibilityErrorInSolutionHint(const MPModelProto& model, const double ub = model.variable(var_index).upper_bound(); if (!IsSmallerWithinTolerance(value, ub, tolerance) || !IsSmallerWithinTolerance(lb, value, tolerance)) { - return StrCat("Variable '", model.variable(var_index).name(), - "' is set to ", absl::LegacyPrecision(value), - " which is not in the variable bounds [", - absl::LegacyPrecision(lb), ", ", absl::LegacyPrecision(ub), - "] modulo a tolerance of ", - absl::LegacyPrecision(tolerance), "."); + return absl::StrCat("Variable '", model.variable(var_index).name(), + "' is set to ", absl::LegacyPrecision(value), + " which is not in the variable bounds [", + absl::LegacyPrecision(lb), ", ", + absl::LegacyPrecision(ub), "] modulo a tolerance of ", + absl::LegacyPrecision(tolerance), "."); } } @@ -247,12 +252,12 @@ std::string FindFeasibilityErrorInSolutionHint(const MPModelProto& model, const double ub = model.constraint(cst_index).upper_bound(); if (!IsSmallerWithinTolerance(activity.Value(), ub, tolerance) || !IsSmallerWithinTolerance(lb, activity.Value(), tolerance)) { - return StrCat("Constraint '", model.constraint(cst_index).name(), - "' has activity ", absl::LegacyPrecision(activity.Value()), - " which is not in the constraint bounds [", - absl::LegacyPrecision(lb), ", ", absl::LegacyPrecision(ub), - "] modulo a tolerance of ", - absl::LegacyPrecision(tolerance), "."); + return absl::StrCat( + "Constraint '", model.constraint(cst_index).name(), "' has activity ", + absl::LegacyPrecision(activity.Value()), + " which is not in the constraint bounds [", absl::LegacyPrecision(lb), + ", ", absl::LegacyPrecision(ub), "] modulo a tolerance of ", + absl::LegacyPrecision(tolerance), "."); } } diff --git a/ortools/lp_data/lp_decomposer.cc b/ortools/lp_data/lp_decomposer.cc index 360b8e0463..ddaf719144 100644 --- a/ortools/lp_data/lp_decomposer.cc +++ b/ortools/lp_data/lp_decomposer.cc @@ -15,6 +15,7 @@ #include +#include "ortools/base/mutex.h" #include "ortools/algorithms/dynamic_partition.h" #include "ortools/lp_data/lp_data.h" #include "ortools/lp_data/lp_utils.h" @@ -31,7 +32,7 @@ LPDecomposer::LPDecomposer() mutex_() {} void LPDecomposer::Decompose(const LinearProgram* linear_problem) { - MutexLock mutex_lock(&mutex_); + absl::MutexLock mutex_lock(&mutex_); original_problem_ = linear_problem; clusters_.clear(); @@ -64,12 +65,12 @@ void LPDecomposer::Decompose(const LinearProgram* linear_problem) { } int LPDecomposer::GetNumberOfProblems() const { - MutexLock mutex_lock(&mutex_); + absl::MutexLock mutex_lock(&mutex_); return clusters_.size(); } const LinearProgram& LPDecomposer::original_problem() const { - MutexLock mutex_lock(&mutex_); + absl::MutexLock mutex_lock(&mutex_); return *original_problem_; } @@ -80,7 +81,7 @@ void LPDecomposer::ExtractLocalProblem(int problem_index, LinearProgram* lp) { lp->Clear(); - MutexLock mutex_lock(&mutex_); + absl::MutexLock mutex_lock(&mutex_); const std::vector& cluster = clusters_[problem_index]; StrictITIVector global_to_local( original_problem_->num_variables(), kInvalidCol); @@ -138,7 +139,7 @@ DenseRow LPDecomposer::AggregateAssignments( const std::vector& assignments) const { CHECK_EQ(assignments.size(), clusters_.size()); - MutexLock mutex_lock(&mutex_); + absl::MutexLock mutex_lock(&mutex_); DenseRow global_assignment(original_problem_->num_variables(), Fractional(0.0)); for (int problem = 0; problem < assignments.size(); ++problem) { @@ -158,7 +159,7 @@ DenseRow LPDecomposer::ExtractLocalAssignment(int problem_index, CHECK_LT(problem_index, clusters_.size()); CHECK_EQ(assignment.size(), original_problem_->num_variables()); - MutexLock mutex_lock(&mutex_); + absl::MutexLock mutex_lock(&mutex_); const std::vector& cluster = clusters_[problem_index]; DenseRow local_assignment(ColIndex(cluster.size()), Fractional(0.0)); for (int i = 0; i < cluster.size(); ++i) { diff --git a/ortools/lp_data/lp_decomposer.h b/ortools/lp_data/lp_decomposer.h index 4d454ae8ec..d26c36762f 100644 --- a/ortools/lp_data/lp_decomposer.h +++ b/ortools/lp_data/lp_decomposer.h @@ -82,7 +82,7 @@ class LPDecomposer { const LinearProgram* original_problem_; std::vector> clusters_; - mutable Mutex mutex_; + mutable absl::Mutex mutex_; DISALLOW_COPY_AND_ASSIGN(LPDecomposer); }; diff --git a/ortools/lp_data/mps_reader.cc b/ortools/lp_data/mps_reader.cc index ed54c6c703..cf98c2e925 100644 --- a/ortools/lp_data/mps_reader.cc +++ b/ortools/lp_data/mps_reader.cc @@ -28,7 +28,7 @@ #include "ortools/base/numbers.h" // for safe_strtod #include "ortools/base/split.h" #include "ortools/base/strutil.h" -#include "ortools/base/map_util.h" // for FindOrNull, FindWithDefault +#include "ortools/base/map_util.h" // for FindOrNull, gtl::FindWithDefault #include "ortools/lp_data/lp_print_utils.h" #include "ortools/base/filelineiter.h" #include "ortools/base/status.h" @@ -211,7 +211,7 @@ void MPSReader::ProcessLine(const std::string& line) { if (line[0] != '\0' && line[0] != ' ') { section = GetFirstWord(); section_ = - FindWithDefault(section_name_to_id_map_, section, UNKNOWN_SECTION); + gtl::FindWithDefault(section_name_to_id_map_, section, UNKNOWN_SECTION); if (section_ == UNKNOWN_SECTION) { if (log_errors_) { LOG(ERROR) << "At line " << line_num_ @@ -295,7 +295,7 @@ void MPSReader::ProcessLine(const std::string& line) { double MPSReader::GetDoubleFromString(const std::string& param) { double result; - if (!safe_strtod(param, &result)) { + if (!strings::safe_strtod(param, &result)) { if (log_errors_) { LOG(ERROR) << "At line " << line_num_ << ": Failed to convert std::string to double. String = " << param @@ -311,7 +311,7 @@ void MPSReader::ProcessRowsSection() { std::string row_type_name = fields_[0]; std::string row_name = fields_[1]; MPSRowType row_type = - FindWithDefault(row_name_to_id_map_, row_type_name, UNKNOWN_ROW_TYPE); + gtl::FindWithDefault(row_name_to_id_map_, row_type_name, UNKNOWN_ROW_TYPE); if (row_type == UNKNOWN_ROW_TYPE) { if (log_errors_) { LOG(ERROR) << "At line " << line_num_ << ": Unknown row type " @@ -499,7 +499,7 @@ void MPSReader::StoreRange(const std::string& row_name, const std::string& range void MPSReader::StoreBound(const std::string& bound_type_mnemonic, const std::string& column_name, const std::string& bound_value) { - const BoundTypeId bound_type_id = FindWithDefault( + const BoundTypeId bound_type_id = gtl::FindWithDefault( bound_name_to_id_map_, bound_type_mnemonic, UNKNOWN_BOUND_TYPE); if (bound_type_id == UNKNOWN_BOUND_TYPE) { parse_success_ = false; diff --git a/ortools/sat/all_different.cc b/ortools/sat/all_different.cc index a66984de79..bc53f76555 100644 --- a/ortools/sat/all_different.cc +++ b/ortools/sat/all_different.cc @@ -435,7 +435,7 @@ void AllDifferentBoundsPropagator::FillHallReason(IntegerValue hall_lb, to_insert_.clear(); integer_reason_.clear(); for (int64 v = hall_lb.value(); v <= hall_ub; ++v) { - const IntegerVariable var = FindOrDie(value_to_variable_, v); + const IntegerVariable var = gtl::FindOrDie(value_to_variable_, v); integer_reason_.push_back(IntegerLiteral::GreaterOrEqual(var, hall_lb)); integer_reason_.push_back(IntegerLiteral::LowerOrEqual(var, hall_ub)); } diff --git a/ortools/sat/boolean_problem.cc b/ortools/sat/boolean_problem.cc index 05f429a6dd..b3da385f20 100644 --- a/ortools/sat/boolean_problem.cc +++ b/ortools/sat/boolean_problem.cc @@ -501,7 +501,7 @@ class IdGenerator { // a new id, otherwise return the previously generated id. int GetId(int type, Coefficient coefficient) { const std::pair key(type, coefficient.value()); - return LookupOrInsert(&id_map_, key, id_map_.size()); + return gtl::LookupOrInsert(&id_map_, key, id_map_.size()); } private: diff --git a/ortools/sat/circuit.cc b/ortools/sat/circuit.cc index 83ac9f2565..803d58ce9e 100644 --- a/ortools/sat/circuit.cc +++ b/ortools/sat/circuit.cc @@ -67,8 +67,8 @@ CircuitPropagator::CircuitPropagator(const int num_nodes, // Tricky: For self-arc, we watch instead when the arc become false. const Literal watched_literal = tail == head ? literal.Negated() : literal; - int watch_index = - FindWithDefault(literal_to_watch_index, watched_literal.Index(), -1); + int watch_index = gtl::FindWithDefault(literal_to_watch_index, + watched_literal.Index(), -1); if (watch_index == -1) { watch_index = watch_index_to_literal_.size(); literal_to_watch_index[watched_literal.Index()] = watch_index; diff --git a/ortools/sat/clause.cc b/ortools/sat/clause.cc index c546642d87..393adf3385 100644 --- a/ortools/sat/clause.cc +++ b/ortools/sat/clause.cc @@ -56,7 +56,7 @@ LiteralWatchers::LiteralWatchers() stats_("LiteralWatchers") {} LiteralWatchers::~LiteralWatchers() { - STLDeleteElements(&clauses_); + gtl::STLDeleteElements(&clauses_); IF_STATS_ENABLED(LOG(INFO) << stats_.StatString()); } @@ -312,7 +312,7 @@ void LiteralWatchers::DeleteDetachedClauses() { std::vector::iterator iter = std::stable_partition(clauses_.begin(), clauses_.end(), [](SatClause* a) { return a->IsAttached(); }); - STLDeleteContainerPointers(iter, clauses_.end()); + gtl::STLDeleteContainerPointers(iter, clauses_.end()); clauses_.erase(iter, clauses_.end()); } @@ -634,8 +634,8 @@ void BinaryImplicationGraph::RemoveFixedVariables( for (Literal lit : implications_[true_literal.NegatedIndex()]) { is_marked_.Set(lit.NegatedIndex()); } - STLClearObject(&(implications_[true_literal.Index()])); - STLClearObject(&(implications_[true_literal.NegatedIndex()])); + gtl::STLClearObject(&(implications_[true_literal.Index()])); + gtl::STLClearObject(&(implications_[true_literal.NegatedIndex()])); } for (const LiteralIndex i : is_marked_.PositionsSetAtLeastOnce()) { RemoveIf(&implications_[i], [&assignment](const Literal& lit) { diff --git a/ortools/sat/clause.h b/ortools/sat/clause.h index 1a09c25454..b411d5f501 100644 --- a/ortools/sat/clause.h +++ b/ortools/sat/clause.h @@ -202,7 +202,7 @@ class LiteralWatchers : public SatPropagator { // that some learned clause are kept forever (heuristics) and do not appear // here. bool IsRemovable(SatClause* const clause) const { - return ContainsKey(clauses_info_, clause); + return gtl::ContainsKey(clauses_info_, clause); } int64 num_removable_clauses() const { return clauses_info_.size(); } std::unordered_map* mutable_clauses_info() { diff --git a/ortools/sat/cp_model_checker.cc b/ortools/sat/cp_model_checker.cc index 9c19c09430..98b6eecfba 100644 --- a/ortools/sat/cp_model_checker.cc +++ b/ortools/sat/cp_model_checker.cc @@ -282,8 +282,8 @@ std::string ValidateCpModel(const CpModelProto& model) { if (model.has_objective()) { for (const int v : model.objective().vars()) { if (!VariableReferenceIsValid(model, v)) { - return StrCat("Out of bound objective variable ", v, " : ", - ProtobufShortDebugString(model.objective())); + return absl::StrCat("Out of bound objective variable ", v, " : ", + ProtobufShortDebugString(model.objective())); } } RETURN_IF_NOT_EMPTY(ValidateObjective(model, model.objective())); @@ -403,7 +403,7 @@ class ConstraintChecker { bool AllDiffConstraintIsFeasible(const ConstraintProto& ct) { std::unordered_set values; for (const int v : ct.all_diff().vars()) { - if (ContainsKey(values, Value(v))) return false; + if (gtl::ContainsKey(values, Value(v))) return false; values.insert(Value(v)); } return true; @@ -535,7 +535,7 @@ class ConstraintChecker { for (int i = 0; i < num_steps; ++i) { const std::pair key = {current_state, Value(ct.automata().vars(i))}; - CHECK(ContainsKey(transition_map, key)); + CHECK(gtl::ContainsKey(transition_map, key)); current_state = transition_map[key]; } diff --git a/ortools/sat/cp_model_expand.cc b/ortools/sat/cp_model_expand.cc index 7d1f65e5c4..3ae53ab19b 100644 --- a/ortools/sat/cp_model_expand.cc +++ b/ortools/sat/cp_model_expand.cc @@ -128,7 +128,7 @@ void ExpandReservoir(ConstraintProto* ct, ExpansionHelper* helper) { const int time_j = reservoir.times(j); const std::pair p = std::make_pair(time_i, time_j); const std::pair rev_p = std::make_pair(time_j, time_i); - if (ContainsKey(helper->precedence_cache, p)) continue; + if (gtl::ContainsKey(helper->precedence_cache, p)) continue; const int i_lesseq_j = helper->AddBoolVar(); helper->precedence_cache[p] = i_lesseq_j; @@ -164,7 +164,7 @@ void ExpandReservoir(ConstraintProto* ct, ExpansionHelper* helper) { for (int j = 0; j < num_variables; ++j) { if (i == j) continue; const int time_j = reservoir.times(j); - level->mutable_linear()->add_vars(FindOrDieNoPrint( + level->mutable_linear()->add_vars(gtl::FindOrDieNoPrint( helper->precedence_cache, std::make_pair(time_j, time_i))); level->mutable_linear()->add_coeffs(reservoir.demands(j)); } diff --git a/ortools/sat/cp_model_presolve.cc b/ortools/sat/cp_model_presolve.cc index 6520dd6b46..872a22480e 100644 --- a/ortools/sat/cp_model_presolve.cc +++ b/ortools/sat/cp_model_presolve.cc @@ -63,7 +63,7 @@ std::vector UsedVariables(const ConstraintProto& ct) { if (HasEnforcementLiteral(ct)) { used_variables.push_back(PositiveRef(ct.enforcement_literal(0))); } - STLSortAndRemoveDuplicates(&used_variables); + gtl::STLSortAndRemoveDuplicates(&used_variables); return used_variables; } @@ -161,7 +161,7 @@ struct PresolveContext { void ExploitFixedDomain(int var) { CHECK(IsFixed(var)); const int min = MinOf(var); - if (ContainsKey(constant_to_ref, min)) { + if (gtl::ContainsKey(constant_to_ref, min)) { const int representative = constant_to_ref[min]; if (representative != var) { affine_relations.TryAdd(var, representative, 1, 0); @@ -474,8 +474,8 @@ bool PresolveIntMax(ConstraintProto* ct, PresolveContext* context) { int new_size = 0; for (const int ref : ct->int_max().vars()) { if (ref == target_ref) contains_target_ref = true; - if (ContainsKey(used_ref, ref)) continue; - if (ContainsKey(used_ref, NegatedRef(ref)) || + if (gtl::ContainsKey(used_ref, ref)) continue; + if (gtl::ContainsKey(used_ref, NegatedRef(ref)) || ref == NegatedRef(target_ref)) { target_min = std::max(target_min, 0ll); } @@ -638,7 +638,7 @@ bool PresolveIntDiv(ConstraintProto* ct, PresolveContext* context) { bool ExploitEquivalenceRelations(ConstraintProto* ct, PresolveContext* context) { - if (ContainsKey(context->affine_constraints, ct)) return false; + if (gtl::ContainsKey(context->affine_constraints, ct)) return false; bool changed = false; // Remap equal and negated variables to their representative. @@ -691,7 +691,7 @@ bool PresolveLinear(ConstraintProto* ct, PresolveContext* context) { int64 sum_of_fixed_terms = 0; std::map var_to_coeff; const LinearConstraintProto& arg = ct->linear(); - const bool was_affine = ContainsKey(context->affine_constraints, ct); + const bool was_affine = gtl::ContainsKey(context->affine_constraints, ct); for (int i = 0; i < arg.vars_size(); ++i) { const int var = PositiveRef(arg.vars(i)); const int64 coeff = @@ -933,7 +933,7 @@ bool PresolveLinear(ConstraintProto* ct, PresolveContext* context) { bool PresolveLinearIntoClauses(ConstraintProto* ct, PresolveContext* context) { // TODO(user): the alternative to mark any newly created constraints might // be better. - if (ContainsKey(context->affine_constraints, ct)) return false; + if (gtl::ContainsKey(context->affine_constraints, ct)) return false; const LinearConstraintProto& arg = ct->linear(); const int num_vars = arg.vars_size(); int64 min_coeff = kint64max; @@ -1010,6 +1010,7 @@ bool PresolveLinearIntoClauses(ConstraintProto* ct, PresolveContext* context) { } bool PresolveInterval(ConstraintProto* ct, PresolveContext* context) { + if (!ct->enforcement_literal().empty()) return false; const int start = ct->interval().start(); const int end = ct->interval().end(); const int size = ct->interval().size(); @@ -1171,7 +1172,7 @@ bool PresolveTable(ConstraintProto* ct, PresolveContext* context) { new_domains[j].insert(RefIsPositive(ref) ? v : -v); } } - STLSortAndRemoveDuplicates(&new_tuples); + gtl::STLSortAndRemoveDuplicates(&new_tuples); // Update the list of tuples if needed. if (new_tuples.size() < num_tuples) { @@ -1227,7 +1228,7 @@ bool PresolveTable(ConstraintProto* ct, PresolveContext* context) { index /= var_to_values[j].size(); } } - STLSortAndRemoveDuplicates(&all_tuples); + gtl::STLSortAndRemoveDuplicates(&all_tuples); // Compute the complement of new_tuples. std::vector> diff(prod - new_tuples.size()); @@ -1472,11 +1473,11 @@ void ExtractClauses(const ClauseContainer& container, CpModelProto* proto) { const int b = clause[1].IsPositive() ? clause[1].Variable().value() : NegatedRef(clause[1].Variable().value()); - if (ContainsKey(ref_to_bool_and, NegatedRef(a))) { + if (gtl::ContainsKey(ref_to_bool_and, NegatedRef(a))) { const int ct_index = ref_to_bool_and[NegatedRef(a)]; proto->mutable_constraints(ct_index)->mutable_bool_and()->add_literals( b); - } else if (ContainsKey(ref_to_bool_and, NegatedRef(b))) { + } else if (gtl::ContainsKey(ref_to_bool_and, NegatedRef(b))) { const int ct_index = ref_to_bool_and[NegatedRef(b)]; proto->mutable_constraints(ct_index)->mutable_bool_and()->add_literals( a); @@ -1799,8 +1800,8 @@ void PresolveCpModel(CpModelProto* presolved_model, CpModelProto* mapping_model, if (constraints.size() != 1) continue; const int c = *constraints.begin(); if (c < 0) continue; - if (ContainsKey(var_constraint_pair_already_called, - std::pair(v, c))) { + if (gtl::ContainsKey(var_constraint_pair_already_called, + std::pair(v, c))) { continue; } var_constraint_pair_already_called.insert({v, c}); @@ -1964,7 +1965,7 @@ void PresolveCpModel(CpModelProto* presolved_model, CpModelProto* mapping_model, // TODO(user): for now we don't remove interval because they can be used // in constraints. ConstraintProto* ct = presolved_model->mutable_constraints(i); - if (ContainsKey(context.affine_constraints, ct)) { + if (gtl::ContainsKey(context.affine_constraints, ct)) { ct->Clear(); context.UpdateConstraintVariableUsage(i); continue; @@ -2056,7 +2057,7 @@ void PresolveCpModel(CpModelProto* presolved_model, CpModelProto* mapping_model, // There is not point having a variable appear twice, so we only keep // the first occurrence in the first strategy in which it occurs. - if (ContainsKey(used_variables, var)) continue; + if (gtl::ContainsKey(used_variables, var)) continue; used_variables.insert(var); if (context.var_to_constraints[var].empty()) { @@ -2130,7 +2131,7 @@ void ApplyVariableMapping(const std::vector& mapping, auto mapping_function = [&mapping](int* ref) { const int image = mapping[PositiveRef(*ref)]; CHECK_GE(image, 0); - *ref = *ref >= 0 ? image : NegatedRef(image); + *ref = RefIsPositive(*ref) ? image : NegatedRef(image); }; for (ConstraintProto& ct_ref : *proto->mutable_constraints()) { ApplyToAllVariableIndices(mapping_function, &ct_ref); @@ -2144,10 +2145,8 @@ void ApplyVariableMapping(const std::vector& mapping, // Remap the objective variables. if (proto->has_objective()) { - for (int& mutable_var : *proto->mutable_objective()->mutable_vars()) { - const int image = mapping[PositiveRef(mutable_var)]; - CHECK_GE(image, 0); - mutable_var = (mutable_var >= 0 ? image : NegatedRef(image)); + for (int& mutable_ref : *proto->mutable_objective()->mutable_vars()) { + mapping_function(&mutable_ref); } } @@ -2159,7 +2158,7 @@ void ApplyVariableMapping(const std::vector& mapping, for (const int ref : copy.variables()) { const int image = mapping[PositiveRef(ref)]; if (image >= 0) { - strategy.add_variables(ref >= 0 ? image : NegatedRef(image)); + strategy.add_variables(RefIsPositive(ref) ? image : NegatedRef(image)); } } strategy.clear_transformations(); @@ -2169,7 +2168,7 @@ void ApplyVariableMapping(const std::vector& mapping, if (image >= 0) { auto* new_transform = strategy.add_transformations(); *new_transform = transform; - new_transform->set_var(ref >= 0 ? image : NegatedRef(image)); + new_transform->set_var(RefIsPositive(ref) ? image : NegatedRef(image)); } } } @@ -2179,15 +2178,21 @@ void ApplyVariableMapping(const std::vector& mapping, auto* mutable_hint = proto->mutable_solution_hint(); int new_size = 0; for (int i = 0; i < mutable_hint->vars_size(); ++i) { - const int image = mapping[PositiveRef(mutable_hint->vars(i))]; + const int ref = mutable_hint->vars(i); + const int image = mapping[PositiveRef(ref)]; if (image >= 0) { - mutable_hint->set_vars(new_size, image); + mutable_hint->set_vars(new_size, + RefIsPositive(ref) ? image : NegatedRef(image)); mutable_hint->set_values(new_size, mutable_hint->values(i)); ++new_size; } } - mutable_hint->mutable_vars()->Truncate(new_size); - mutable_hint->mutable_values()->Truncate(new_size); + if (new_size > 0) { + mutable_hint->mutable_vars()->Truncate(new_size); + mutable_hint->mutable_values()->Truncate(new_size); + } else { + proto->clear_solution_hint(); + } } // Move the variable definitions. diff --git a/ortools/sat/cp_model_search.cc b/ortools/sat/cp_model_search.cc index 73a8fbf1bf..8403a99da6 100644 --- a/ortools/sat/cp_model_search.cc +++ b/ortools/sat/cp_model_search.cc @@ -56,9 +56,9 @@ const std::function ConstructSearchStrategyInternal( IntegerValue value(0); IntegerValue coeff(1); IntegerValue offset(0); - if (ContainsKey(var_to_coeff_offset_pair, var.value())) { + if (gtl::ContainsKey(var_to_coeff_offset_pair, var.value())) { const auto coeff_offset = - FindOrDie(var_to_coeff_offset_pair, var.value()); + gtl::FindOrDie(var_to_coeff_offset_pair, var.value()); coeff = coeff_offset.first; offset = coeff_offset.second; } @@ -158,7 +158,7 @@ std::function ConstructSearchStrategy( const IntegerVariable var = RefIsPositive(ref) ? variable_mapping[ref] : NegationOf(variable_mapping[PositiveRef(ref)]); - if (!ContainsKey(var_to_coeff_offset_pair, var.value())) { + if (!gtl::ContainsKey(var_to_coeff_offset_pair, var.value())) { var_to_coeff_offset_pair[var.value()] = {tranform.positive_coeff(), tranform.offset()}; } @@ -189,7 +189,8 @@ std::function InstrumentSearchStrategy( if (decision == kNoLiteralIndex) return decision; const int level = model->Get()->CurrentDecisionLevel(); - std::string to_display = StrCat("Diff since last call, level=", level, "\n"); + std::string to_display = + absl::StrCat("Diff since last call, level=", level, "\n"); IntegerTrail* integer_trail = model->GetOrCreate(); for (const int ref : ref_to_display) { const IntegerVariable var = variable_mapping[ref]; @@ -198,8 +199,8 @@ std::function InstrumentSearchStrategy( integer_trail->UpperBound(var).value()); if (new_domain != old_domains[ref]) { old_domains[ref] = new_domain; - StrAppend(&to_display, cp_model_proto.variables(ref).name(), " [", - new_domain.first, ",", new_domain.second, "]\n"); + absl::StrAppend(&to_display, cp_model_proto.variables(ref).name(), " [", + new_domain.first, ",", new_domain.second, "]\n"); } } LOG(INFO) << to_display; diff --git a/ortools/sat/cp_model_solver.cc b/ortools/sat/cp_model_solver.cc index 4ca2208ea5..1019b891c1 100644 --- a/ortools/sat/cp_model_solver.cc +++ b/ortools/sat/cp_model_solver.cc @@ -71,6 +71,9 @@ DEFINE_string(cp_model_dump_file, "", "SolveCpModel() will dump its model to this file. Note that the " "file will be ovewritten with the last such model. " "TODO(fdid): dump all model to a recordio file instead?"); +DEFINE_string(cp_model_params, "", + "This is interpreted as a text SatParameters proto. The " + "specified fields will override the normal ones for all solves."); DEFINE_string( drat_output, "", @@ -220,7 +223,7 @@ class ModelWithMapping { // skip constraints that correspond to a basic encoding detected by // ExtractEncoding(). bool IgnoreConstraint(const ConstraintProto* ct) const { - return ContainsKey(ct_to_ignore_, ct); + return gtl::ContainsKey(ct_to_ignore_, ct); } Model* model() const { return model_; } @@ -556,7 +559,7 @@ ModelWithMapping::ModelWithMapping(const CpModelProto& model_proto, for (int& ref : var_to_instantiate_as_integer) { if (!RefIsPositive(ref)) ref = PositiveRef(ref); } - STLSortAndRemoveDuplicates(&var_to_instantiate_as_integer); + gtl::STLSortAndRemoveDuplicates(&var_to_instantiate_as_integer); } integers_.resize(num_proto_variables, kNoIntegerVariable); for (const int i : var_to_instantiate_as_integer) { @@ -646,7 +649,7 @@ class FullEncodingFixedPointComputer { const int variable = variables_to_propagate_.back(); variables_to_propagate_.pop_back(); for (const ConstraintProto* ct : variable_watchers_[variable]) { - if (ContainsKey(constraint_is_finished_, ct)) continue; + if (gtl::ContainsKey(constraint_is_finished_, ct)) continue; const bool finished = PropagateFullEncoding(ct); if (finished) constraint_is_finished_.insert(ct); } @@ -675,7 +678,7 @@ class FullEncodingFixedPointComputer { // Constraint ct is interested by (full-encoding) state of variable. void Register(const ConstraintProto* ct, int variable) { variable = PositiveRef(variable); - if (!ContainsKey(constraint_is_registered_, ct)) { + if (!gtl::ContainsKey(constraint_is_registered_, ct)) { constraint_is_registered_.insert(ct); } if (variable_watchers_.size() <= variable) { @@ -756,7 +759,7 @@ bool FullEncodingFixedPointComputer::PropagateElement( } // If some variables are not fully encoded, register on those. - if (!ContainsKey(constraint_is_registered_, ct)) { + if (!gtl::ContainsKey(constraint_is_registered_, ct)) { for (const int v : ct->element().vars()) Register(ct, v); Register(ct, target); } @@ -798,7 +801,7 @@ bool FullEncodingFixedPointComputer::PropagateLinear( if (ct->linear().domain(0) != ct->linear().domain(1)) return true; // If some domain is too large, abort; - if (!ContainsKey(constraint_is_registered_, ct)) { + if (!gtl::ContainsKey(constraint_is_registered_, ct)) { for (const int v : ct->linear().vars()) { const IntegerVariable var = model_->Integer(v); IntegerTrail* integer_trail = model_->GetOrCreate(); @@ -835,7 +838,7 @@ bool FullEncodingFixedPointComputer::PropagateLinear( if (num_fully_encoded == num_vars) return true; // Register on remaining variables if not already done. - if (!ContainsKey(constraint_is_registered_, ct)) { + if (!gtl::ContainsKey(constraint_is_registered_, ct)) { for (const int var : ct->linear().vars()) { if (!IsFullyEncoded(var)) Register(ct, var); } @@ -1166,7 +1169,7 @@ void LoadElementConstraintAC(const ConstraintProto& ct, ModelWithMapping* m) { const IntegerValue value = var_literal_value.value; const Literal var_is_value = var_literal_value.literal; - if (!ContainsKey(target_map, value)) { + if (!gtl::ContainsKey(target_map, value)) { // No need to add to value_to_literals, selected[i][value] is always // false. m->Add(Implication(i_lit, var_is_value.Negated())); @@ -1188,7 +1191,7 @@ void LoadElementConstraintAC(const ConstraintProto& ct, ModelWithMapping* m) { const IntegerValue value = entry.first; const Literal target_is_value = entry.second; - if (!ContainsKey(value_to_literals, value)) { + if (!gtl::ContainsKey(value_to_literals, value)) { m->Add(ClauseConstraint({target_is_value.Negated()})); } else { m->Add(ReifiedBoolOr(value_to_literals[value], target_is_value)); @@ -1394,8 +1397,8 @@ void LoadInverseConstraint(const ConstraintProto& ct, ModelWithMapping* m) { std::string Summarize(const std::string& input) { if (input.size() < 105) return input; const int half = 50; - return StrCat(input.substr(0, half), " ... ", - input.substr(input.size() - half, half)); + return absl::StrCat(input.substr(0, half), " ... ", + input.substr(input.size() - half, half)); } } // namespace. @@ -1831,7 +1834,7 @@ void TryToLinearizeConstraint( auto get_constraint = [](std::map>* node_map, int node) { - if (!ContainsKey(*node_map, node)) { + if (!gtl::ContainsKey(*node_map, node)) { (*node_map)[node].reset(new LinearConstraintBuilder(1, 1)); } return (*node_map)[node].get(); @@ -2077,7 +2080,7 @@ IntegerVariable AddLPConstraints(const CpModelProto& model_proto, for (int i = 0; i < num_lp_constraints; i++) { const int id = components.GetClassRepresentative(get_constraint_index(i)); if (components_to_size[id] <= 1) continue; - if (!ContainsKey(representative_to_lp_constraint, id)) { + if (!gtl::ContainsKey(representative_to_lp_constraint, id)) { auto* lp = m->model()->Create(); representative_to_lp_constraint[id] = lp; lp_constraints.push_back(lp); @@ -2097,7 +2100,7 @@ IntegerVariable AddLPConstraints(const CpModelProto& model_proto, for (int i = 0; i < num_lp_cut_generators; i++) { const int id = components.GetClassRepresentative(get_cut_generator_index(i)); - if (!ContainsKey(representative_to_lp_constraint, id)) { + if (!gtl::ContainsKey(representative_to_lp_constraint, id)) { auto* lp = m->model()->Create(); representative_to_lp_constraint[id] = lp; lp_constraints.push_back(lp); @@ -2118,7 +2121,7 @@ IntegerVariable AddLPConstraints(const CpModelProto& model_proto, const IntegerVariable var = m->Integer(model_proto.objective().vars(i)); const int64 coeff = model_proto.objective().coeffs(i); const int id = components.GetClassRepresentative(get_var_index(var)); - if (ContainsKey(representative_to_lp_constraint, id)) { + if (gtl::ContainsKey(representative_to_lp_constraint, id)) { representative_to_lp_constraint[id]->SetObjectiveCoefficient(var, coeff); representative_to_cp_terms[id].push_back(std::make_pair(var, coeff)); @@ -2131,7 +2134,7 @@ IntegerVariable AddLPConstraints(const CpModelProto& model_proto, for (const auto& it : representative_to_cp_terms) { const int id = it.first; LinearProgrammingConstraint* lp = - FindOrDie(representative_to_lp_constraint, id); + gtl::FindOrDie(representative_to_lp_constraint, id); const std::vector>& terms = it.second; const IntegerVariable sub_obj_var = GetOrCreateVariableGreaterOrEqualToSumOf(terms, m->model()); @@ -2405,7 +2408,7 @@ CpSolverResponse SolveCpModelInternal( // reset the solver to its initial state, but then with phase saving it // should still follow the same path again. if (model_proto.has_solution_hint()) { - VLOG(0) << "Loading solution hint ... "; + LOG(INFO) << "Loading solution hint ... "; const int64 old_conflict_limit = parameters.max_number_of_conflicts(); model->GetOrCreate()->set_max_number_of_conflicts(10); std::vector vars; @@ -2429,9 +2432,9 @@ CpSolverResponse SolveCpModelInternal( status = SolveProblemWithPortfolioSearch(decision_policies, {no_restart}, model); if (status == SatSolver::Status::MODEL_SAT) { - VLOG(0) << "Solution hint: success, feasible solution found."; + LOG(INFO) << "Solution hint: success, feasible solution found."; } else { - VLOG(0) << "Solution: failure, no feasible solution found."; + LOG(INFO) << "Solution: failure, no feasible solution found."; } model->GetOrCreate()->set_max_number_of_conflicts( old_conflict_limit); @@ -2750,6 +2753,17 @@ CpSolverResponse SolveCpModel(const CpModelProto& model_proto, Model* model) { CHECK_OK(file::SetBinaryProto(FLAGS_cp_model_dump_file, model_proto, file::Defaults())); } + + // Override parameters? + if (!FLAGS_cp_model_params.empty()) { + SatParameters params = *model->GetOrCreate(); + SatParameters flag_params; + CHECK(google::protobuf::TextFormat::ParseFromString(FLAGS_cp_model_params, + &flag_params)); + params.MergeFrom(flag_params); + model->Add(NewSatParameters(params)); + LOG(INFO) << "Parameters: " << params.ShortDebugString(); + } #endif // __PORTABLE_PLATFORM__ // Special case for pure-sat problem. diff --git a/ortools/sat/cumulative.cc b/ortools/sat/cumulative.cc index ad5af3f959..5825912acb 100644 --- a/ortools/sat/cumulative.cc +++ b/ortools/sat/cumulative.cc @@ -123,7 +123,7 @@ std::function Cumulative( IntegerTrail* integer_trail = model->GetOrCreate(); SchedulingConstraintHelper* helper = - new SchedulingConstraintHelper(vars, trail, integer_trail, intervals); + new SchedulingConstraintHelper(vars, model); model->TakeOwnership(helper); // Propagator responsible for applying Timetabling filtering rule. It diff --git a/ortools/sat/disjunctive.cc b/ortools/sat/disjunctive.cc index 7aba13d4f3..3e5e255e97 100644 --- a/ortools/sat/disjunctive.cc +++ b/ortools/sat/disjunctive.cc @@ -46,9 +46,8 @@ std::function Disjunctive( return; } - SchedulingConstraintHelper* helper = new SchedulingConstraintHelper( - vars, model->GetOrCreate(), model->GetOrCreate(), - repository); + SchedulingConstraintHelper* helper = + new SchedulingConstraintHelper(vars, model); model->TakeOwnership(helper); GenericLiteralWatcher* watcher = model->GetOrCreate(); @@ -345,7 +344,7 @@ bool DisjunctiveDetectablePrecedences::Propagate() { // From there, we deduce that the start-min of t is greater or equal to the // end-min of the critical tasks. // - // Note that this works as well when task_is_currently_present_[t] is false. + // Note that this works as well when IsPresent(t) is false. int critical_index = 0; const IntegerValue min_end_of_critical_tasks = task_set_.ComputeEndMin(/*task_to_ignore=*/t, &critical_index); @@ -405,7 +404,7 @@ bool DisjunctivePrecedences::Propagate() { task_is_currently_present_, &before_); // We don't care about the initial content of this vector. - reason_for_beeing_before_.resize(num_tasks, kNoLiteralIndex); + reason_for_being_before_.resize(num_tasks, absl::InlinedVector()); int critical_index; const int size = before_.size(); for (int i = 0; i < size;) { @@ -414,7 +413,7 @@ bool DisjunctivePrecedences::Propagate() { task_set_.Clear(); for (; i < size && before_[i].var == var; ++i) { const int task = before_[i].index; - reason_for_beeing_before_[task] = before_[i].reason; + reason_for_being_before_[task] = before_[i].reason; task_set_.AddUnsortedEntry( {task, helper_->StartMin(task), helper_->DurationMin(task)}); } @@ -436,9 +435,8 @@ bool DisjunctivePrecedences::Propagate() { helper_->AddPresenceReason(ct); helper_->AddDurationMinReason(ct); helper_->AddStartMinReason(ct, window_start); - if (reason_for_beeing_before_[ct] != kNoLiteralIndex) { - helper_->MutableLiteralReason()->push_back( - Literal(reason_for_beeing_before_[ct]).Negated()); + for (const Literal l : reason_for_being_before_[ct]) { + helper_->MutableLiteralReason()->push_back(l.Negated()); } } diff --git a/ortools/sat/disjunctive.h b/ortools/sat/disjunctive.h index 9b3bc2ba75..00497059bc 100644 --- a/ortools/sat/disjunctive.h +++ b/ortools/sat/disjunctive.h @@ -218,7 +218,7 @@ class DisjunctivePrecedences : public PropagatorInterface { TaskSet task_set_; std::vector task_is_currently_present_; - std::vector reason_for_beeing_before_; + std::vector> reason_for_being_before_; std::vector before_; }; diff --git a/ortools/sat/integer.cc b/ortools/sat/integer.cc index 4000b19cc4..540653a75b 100644 --- a/ortools/sat/integer.cc +++ b/ortools/sat/integer.cc @@ -57,7 +57,7 @@ void IntegerEncoder::FullyEncodeVariable(IntegerVariable var) { } else { for (int i = 0; i < values.size(); ++i) { const std::pair key{var, values[i]}; - if (ContainsKey(equality_to_associated_literal_, key)) { + if (gtl::ContainsKey(equality_to_associated_literal_, key)) { literals.push_back(equality_to_associated_literal_[key]); } else { literals.push_back(Literal(sat_solver_->NewBooleanVariable(), true)); @@ -117,7 +117,7 @@ IntegerEncoder::FullDomainEncoding(IntegerVariable var) const { for (IntegerValue value(interval.start); value <= interval.end; ++value) { const std::pair key{var, value}; const Literal literal = - FindOrDieNoPrint(equality_to_associated_literal_, key); + gtl::FindOrDieNoPrint(equality_to_associated_literal_, key); if (sat_solver_->Assignment().LiteralIsTrue(literal)) { return {{value, literal}}; } else if (!sat_solver_->Assignment().LiteralIsFalse(literal)) { @@ -167,7 +167,7 @@ void IntegerEncoder::AddImplications(IntegerLiteral i_lit, Literal literal) { std::map& map_ref = encoding_by_var_[IntegerVariable(i_lit.var)]; - CHECK(!ContainsKey(map_ref, i_lit.bound)); + CHECK(!gtl::ContainsKey(map_ref, i_lit.bound)); if (add_implications_) { auto after_it = map_ref.lower_bound(i_lit.bound); @@ -291,7 +291,7 @@ void IntegerEncoder::AssociateToIntegerEqualValue(Literal literal, IntegerVariable var, IntegerValue value) { const std::pair key{var, value}; - if (ContainsKey(equality_to_associated_literal_, key)) { + if (gtl::ContainsKey(equality_to_associated_literal_, key)) { // If this key is already associated, make the two literals equal. const Literal representative = equality_to_associated_literal_[key]; if (representative != literal) { @@ -530,11 +530,11 @@ IntegerVariable IntegerTrail::AddIntegerVariable( std::vector IntegerTrail::InitialVariableDomain( IntegerVariable var) const { const int interval_index = - FindWithDefault(var_to_current_lb_interval_index_, var, -1); + gtl::FindWithDefault(var_to_current_lb_interval_index_, var, -1); if (interval_index >= 0) { return std::vector( &all_intervals_[interval_index], - &all_intervals_[FindOrDie(var_to_end_interval_index_, var)]); + &all_intervals_[gtl::FindOrDie(var_to_end_interval_index_, var)]); } else { std::vector result; result.push_back({LevelZeroBound(var).value(), @@ -569,7 +569,7 @@ bool IntegerTrail::UpdateInitialDomain(IntegerVariable var, {})); // TODO(user): reuse the memory if possible. - if (ContainsKey(var_to_current_lb_interval_index_, var)) { + if (gtl::ContainsKey(var_to_current_lb_interval_index_, var)) { var_to_current_lb_interval_index_.EraseOrDie(var); var_to_end_interval_index_.erase(var); var_to_current_lb_interval_index_.EraseOrDie(NegationOf(var)); @@ -580,7 +580,7 @@ bool IntegerTrail::UpdateInitialDomain(IntegerVariable var, for (const ClosedInterval interval : domain) { all_intervals_.push_back(interval); } - InsertOrDie(&var_to_end_interval_index_, var, all_intervals_.size()); + gtl::InsertOrDie(&var_to_end_interval_index_, var, all_intervals_.size()); // Copy for the negated variable. var_to_current_lb_interval_index_.Set(NegationOf(var), @@ -588,8 +588,8 @@ bool IntegerTrail::UpdateInitialDomain(IntegerVariable var, for (const ClosedInterval interval : ::gtl::reversed_view(domain)) { all_intervals_.push_back({-interval.end, -interval.start}); } - InsertOrDie(&var_to_end_interval_index_, NegationOf(var), - all_intervals_.size()); + gtl::InsertOrDie(&var_to_end_interval_index_, NegationOf(var), + all_intervals_.size()); } // If the variable is fully encoded, set to false excluded literals. @@ -622,7 +622,8 @@ IntegerVariable IntegerTrail::GetOrCreateConstantIntegerVariable( if (insert.second) { // new element. const IntegerVariable new_var = AddIntegerVariable(value, value); insert.first->second = new_var; - if (value != 0) InsertOrDie(&constant_map_, -value, NegationOf(new_var)); + if (value != 0) + gtl::InsertOrDie(&constant_map_, -value, NegationOf(new_var)); } return insert.first->second; } @@ -802,9 +803,9 @@ bool IntegerTrail::Enqueue(IntegerLiteral i_lit, // we always map these to enqueued literals during conflict resolution. { int interval_index = - FindWithDefault(var_to_current_lb_interval_index_, var, -1); + gtl::FindWithDefault(var_to_current_lb_interval_index_, var, -1); if (interval_index >= 0) { - const int end_index = FindOrDie(var_to_end_interval_index_, var); + const int end_index = gtl::FindOrDie(var_to_end_interval_index_, var); while (interval_index < end_index && i_lit.bound > all_intervals_[interval_index].end) { ++interval_index; @@ -1108,7 +1109,7 @@ void IntegerTrail::MergeReasonIntoInternal(std::vector* output) const { for (const IntegerVariable var : tmp_to_clear_) { tmp_var_to_trail_index_in_queue_[var] = 0; } - STLSortAndRemoveDuplicates(output); + gtl::STLSortAndRemoveDuplicates(output); } absl::Span IntegerTrail::Reason(const Trail& trail, diff --git a/ortools/sat/integer.h b/ortools/sat/integer.h index 275f636f6b..ce238fd54c 100644 --- a/ortools/sat/integer.h +++ b/ortools/sat/integer.h @@ -495,7 +495,14 @@ class IntegerTrail : public SatPropagator { DCHECK(IsOptional(i)); return Literal(is_ignored_literals_[i]); } + LiteralIndex OptionalLiteralIndex(IntegerVariable i) const { + return is_ignored_literals_[i] == kNoLiteralIndex + ? kNoLiteralIndex + : Literal(is_ignored_literals_[i]).NegatedIndex(); + } void MarkIntegerVariableAsOptional(IntegerVariable i, Literal is_considered) { + DCHECK(is_ignored_literals_[i] == kNoLiteralIndex || + is_ignored_literals_[i] == is_considered.NegatedIndex()); is_ignored_literals_[i] = is_considered.NegatedIndex(); is_ignored_literals_[NegationOf(i)] = is_considered.NegatedIndex(); } @@ -524,6 +531,10 @@ class IntegerTrail : public SatPropagator { // IMPORTANT: Notice the inversed sign in the literal reason. This is a bit // confusing but internally SAT use this direction for efficiency. // + // Note(user): Duplicates Literal/IntegerLiteral are supported because we call + // STLSortAndRemoveDuplicates() in MergeReasonInto(), but maybe they shouldn't + // for efficiency reason. + // // TODO(user): provide an API to give the reason lazily. // // TODO(user): If the given bound is equal to the current bound, maybe the new diff --git a/ortools/sat/integer_expr.cc b/ortools/sat/integer_expr.cc index ab1bfd2e7d..1e3958b038 100644 --- a/ortools/sat/integer_expr.cc +++ b/ortools/sat/integer_expr.cc @@ -540,7 +540,7 @@ std::function IsOneOf(IntegerVariable var, unique_values.push_back(values[i].value()); value_to_selector[values[i].value()].push_back(selectors[i]); } - STLSortAndRemoveDuplicates(&unique_values); + gtl::STLSortAndRemoveDuplicates(&unique_values); integer_trail->UpdateInitialDomain( var, SortedDisjointIntervalsFromValues(unique_values)); diff --git a/ortools/sat/integer_search.cc b/ortools/sat/integer_search.cc index 9dc20d04ee..d3e5612be6 100644 --- a/ortools/sat/integer_search.cc +++ b/ortools/sat/integer_search.cc @@ -192,7 +192,7 @@ std::function ExploitIntegerLpSolution( const IntegerVariable positive_var = VariableIsPositive(l.var) ? l.var : NegationOf(l.var); LinearProgrammingConstraint* lp = - FindWithDefault(*lp_dispatcher, positive_var, nullptr); + gtl::FindWithDefault(*lp_dispatcher, positive_var, nullptr); if (lp != nullptr) { const IntegerValue value = IntegerValue(static_cast( std::round(lp->GetSolutionValue(positive_var)))); diff --git a/ortools/sat/intervals.cc b/ortools/sat/intervals.cc index cd86b8e59b..2ccbf2e86e 100644 --- a/ortools/sat/intervals.cc +++ b/ortools/sat/intervals.cc @@ -34,29 +34,23 @@ IntervalVariable IntervalsRepository::CreateInterval(IntegerVariable start, is_present_.push_back(is_present); // Link properly all its components. - if (SizeVar(i) != kNoIntegerVariable) { - precedences_->AddPrecedenceWithVariableOffset(StartVar(i), EndVar(i), - SizeVar(i)); - precedences_->AddPrecedenceWithVariableOffset(EndVar(i), StartVar(i), - NegationOf(SizeVar(i))); - } else { - precedences_->AddPrecedenceWithOffset(StartVar(i), EndVar(i), fixed_size); - precedences_->AddPrecedenceWithOffset(EndVar(i), StartVar(i), -fixed_size); - } - if (IsOptional(i)) { - const Literal literal(is_present); - integer_trail_->MarkIntegerVariableAsOptional(StartVar(i), literal); - integer_trail_->MarkIntegerVariableAsOptional(EndVar(i), literal); - } + precedences_->AddPrecedenceWithAllOptions(StartVar(i), EndVar(i), fixed_size, + SizeVar(i), is_present); + precedences_->AddPrecedenceWithAllOptions(EndVar(i), StartVar(i), -fixed_size, + SizeVar(i) == kNoIntegerVariable + ? kNoIntegerVariable + : NegationOf(SizeVar(i)), + is_present); return i; } SchedulingConstraintHelper::SchedulingConstraintHelper( - const std::vector& tasks, Trail* trail, - IntegerTrail* integer_trail, IntervalsRepository* repository) - : trail_(trail), - integer_trail_(integer_trail), + const std::vector& tasks, Model* model) + : trail_(model->GetOrCreate()), + integer_trail_(model->GetOrCreate()), + precedences_(model->GetOrCreate()), current_time_direction_(true) { + auto* repository = model->GetOrCreate(); start_vars_.clear(); end_vars_.clear(); minus_end_vars_.clear(); @@ -159,58 +153,46 @@ bool SchedulingConstraintHelper::PushIntegerLiteral(IntegerLiteral bound) { return integer_trail_->Enqueue(bound, literal_reason_, integer_reason_); } -bool SchedulingConstraintHelper::IncreaseStartMin(int t, - IntegerValue new_min_start) { - if (!integer_trail_->Enqueue( - IntegerLiteral::GreaterOrEqual(start_vars_[t], new_min_start), - literal_reason_, integer_reason_)) { - return false; - } - - // Skip if the task is now absent. +bool SchedulingConstraintHelper::PushIntervalBound(int t, IntegerLiteral lit) { if (IsAbsent(t)) return true; - // We propagate right away the new end-min lower-bound we have. - const IntegerValue min_end_lb = new_min_start + DurationMin(t); - if (EndMin(t) < min_end_lb) { - ClearReason(); - AddStartMinReason(t, new_min_start); - AddDurationMinReason(t); - if (!integer_trail_->Enqueue( - IntegerLiteral::GreaterOrEqual(end_vars_[t], min_end_lb), - literal_reason_, integer_reason_)) { - return false; + // TODO(user): we can also push lit.var if its presence implies the interval + // presence. + if (IsOptional(t) && integer_trail_->OptionalLiteralIndex(lit.var) != + reason_for_presence_[t]) { + if (IsPresent(t)) { + // We can still push, but we do need the presence reason. + AddPresenceReason(t); + } else { + // In this case we cannot push lit.var, but we may detect the interval + // absence. + if (lit.bound > integer_trail_->UpperBound(lit.var)) { + integer_reason_.push_back( + IntegerLiteral::LowerOrEqual(lit.var, lit.bound - 1)); + PushTaskAbsence(t); + } + return true; } } - return true; + if (!integer_trail_->Enqueue(lit, literal_reason_, integer_reason_)) { + return false; + } + + if (IsAbsent(t)) return true; + return precedences_->PropagateOutgoingArcs(lit.var); +} + +bool SchedulingConstraintHelper::IncreaseStartMin(int t, + IntegerValue new_min_start) { + return PushIntervalBound( + t, IntegerLiteral::GreaterOrEqual(start_vars_[t], new_min_start)); } bool SchedulingConstraintHelper::DecreaseEndMax(int t, IntegerValue new_max_end) { - if (!integer_trail_->Enqueue( - IntegerLiteral::LowerOrEqual(end_vars_[t], new_max_end), - literal_reason_, integer_reason_)) { - return false; - } - - // Skip if the task is now absent. - if (IsAbsent(t)) return true; - - // We propagate right away the new start-max upper-bound we have. - const IntegerValue max_start_ub = new_max_end - DurationMin(t); - if (StartMax(t) > max_start_ub) { - ClearReason(); - AddEndMaxReason(t, new_max_end); - AddDurationMinReason(t); - if (!integer_trail_->Enqueue( - IntegerLiteral::LowerOrEqual(start_vars_[t], max_start_ub), - literal_reason_, integer_reason_)) { - return false; - } - } - - return true; + return PushIntervalBound( + t, IntegerLiteral::LowerOrEqual(end_vars_[t], new_max_end)); } void SchedulingConstraintHelper::PushTaskAbsence(int t) { diff --git a/ortools/sat/intervals.h b/ortools/sat/intervals.h index 34e47f8d86..709950af10 100644 --- a/ortools/sat/intervals.h +++ b/ortools/sat/intervals.h @@ -54,11 +54,6 @@ class IntervalsRepository { // Functions to add a new interval to the repository. // - If size == kNoIntegerVariable, then the size is fixed to fixed_size. // - If is_present != kNoLiteralIndex, then this is an optional interval. - // - // TRICKY: for optional interval, the start and end variables are - // automatically marked as "ignorable" and the relation start + size <= end - // will still be propagated even if the interval is not present. Note that we - // never mark the size as "ignorable" here. IntervalVariable CreateInterval(IntegerVariable start, IntegerVariable end, IntegerVariable size, IntegerValue fixed_size, LiteralIndex is_present); @@ -124,8 +119,7 @@ class SchedulingConstraintHelper { // All the functions below refer to a task by its index t in the tasks // vector given at construction. SchedulingConstraintHelper(const std::vector& tasks, - Trail* trail, IntegerTrail* integer_trail, - IntervalsRepository* intervals_repository); + Model* model); // Returns the number of task. int NumTasks() const { return start_vars_.size(); } @@ -148,9 +142,13 @@ class SchedulingConstraintHelper { IntegerValue EndMin(int t) const; IntegerValue EndMax(int t) const; + bool StartIsFixed(int t) const; + bool EndIsFixed(int t) const; + // Returns true if the corresponding fact is known for sure. A normal task is // always present. For optional task for which the presence is still unknown, // both of these function will return false. + bool IsOptional(int t) const; bool IsPresent(int t) const; bool IsAbsent(int t) const; @@ -191,6 +189,12 @@ class SchedulingConstraintHelper { // Push something using the current reason. Note that IncreaseStartMin() will // also increase the end-min, and DecreaseEndMax() will also decrease the // start-max. + // + // Important: IncreaseStartMin() and DecreaseEndMax() can be called on an + // optional interval whose presence is still unknown and push a bound + // conditionned on its presence. The functions will do the correct thing + // depending on whether or not the start_min/end_max are optional variables + // whose presence implies the interval presence. bool IncreaseStartMin(int t, IntegerValue new_min_start); bool DecreaseEndMax(int t, IntegerValue new_max_end); void PushTaskAbsence(int t); @@ -206,8 +210,12 @@ class SchedulingConstraintHelper { void WatchAllTasks(int id, GenericLiteralWatcher* watcher) const; private: + // Internal function for IncreaseStartMin()/DecreaseEndMax(). + bool PushIntervalBound(int t, IntegerLiteral lit); + Trail* trail_; IntegerTrail* integer_trail_; + PrecedencesPropagator* precedences_; // All the underlying variables of the tasks. // The vectors are indexed by the task index t. @@ -268,6 +276,18 @@ inline IntegerValue SchedulingConstraintHelper::EndMax(int t) const { return integer_trail_->UpperBound(end_vars_[t]); } +inline bool SchedulingConstraintHelper::StartIsFixed(int t) const { + return StartMin(t) == StartMax(t); +} + +inline bool SchedulingConstraintHelper::EndIsFixed(int t) const { + return EndMin(t) == EndMax(t); +} + +inline bool SchedulingConstraintHelper::IsOptional(int t) const { + return reason_for_presence_[t] != kNoLiteralIndex; +} + inline bool SchedulingConstraintHelper::IsPresent(int t) const { if (reason_for_presence_[t] == kNoLiteralIndex) return true; return trail_->Assignment().LiteralIsTrue(Literal(reason_for_presence_[t])); @@ -417,6 +437,23 @@ inline std::function NewOptionalInterval( }; } +inline std::function +NewOptionalIntervalWithOptionalVariables(int64 min_start, int64 max_end, + int64 size, Literal is_present) { + return [=](Model* model) { + // Note that we need to mark the optionality first. + const IntegerVariable start = + model->Add(NewIntegerVariable(min_start, max_end)); + const IntegerVariable end = + model->Add(NewIntegerVariable(min_start, max_end)); + auto* integer_trail = model->GetOrCreate(); + integer_trail->MarkIntegerVariableAsOptional(start, is_present); + integer_trail->MarkIntegerVariableAsOptional(end, is_present); + return model->GetOrCreate()->CreateInterval( + start, end, kNoIntegerVariable, IntegerValue(size), is_present.Index()); + }; +} + inline std::function NewOptionalInterval( IntegerVariable start, IntegerVariable end, IntegerVariable size, Literal is_present) { @@ -439,20 +476,6 @@ NewOptionalIntervalWithVariableSize(int64 min_start, int64 max_end, }; } -inline std::function NewIntervalFromStartAndSizeVars( - IntegerVariable start, IntegerVariable size) { - return [=](Model* model) { - // Create the "end" variable. - // TODO(user): deal with overflow. - IntegerTrail* t = model->GetOrCreate(); - const IntegerValue end_lb = t->LowerBound(start) + t->LowerBound(size); - const IntegerValue end_ub = t->UpperBound(start) + t->UpperBound(size); - const IntegerVariable end = t->AddIntegerVariable(end_lb, end_ub); - return model->GetOrCreate()->CreateInterval( - start, end, size, IntegerValue(0), kNoLiteralIndex); - }; -} - // This requires that all the alternatives are optional tasks. inline std::function IntervalWithAlternatives( IntervalVariable master, const std::vector& members) { diff --git a/ortools/sat/linear_programming_constraint.cc b/ortools/sat/linear_programming_constraint.cc index 367429afbc..73072ca0d7 100644 --- a/ortools/sat/linear_programming_constraint.cc +++ b/ortools/sat/linear_programming_constraint.cc @@ -59,7 +59,7 @@ LinearProgrammingConstraint::CreateNewConstraint(double lb, double ub) { glop::ColIndex LinearProgrammingConstraint::GetOrCreateMirrorVariable( IntegerVariable positive_variable) { DCHECK(VariableIsPositive(positive_variable)); - if (!ContainsKey(mirror_lp_variable_, positive_variable)) { + if (!gtl::ContainsKey(mirror_lp_variable_, positive_variable)) { const glop::ColIndex col = lp_data_.CreateNewVariable(); DCHECK_EQ(col, integer_variables_.size()); mirror_lp_variable_[positive_variable] = col; @@ -185,12 +185,13 @@ glop::Fractional LinearProgrammingConstraint::GetVariableValueAtCpScale( double LinearProgrammingConstraint::GetSolutionValue( IntegerVariable variable) const { - return lp_solution_[FindOrDie(mirror_lp_variable_, variable).value()]; + return lp_solution_[gtl::FindOrDie(mirror_lp_variable_, variable).value()]; } double LinearProgrammingConstraint::GetSolutionReducedCost( IntegerVariable variable) const { - return lp_reduced_cost_[FindOrDie(mirror_lp_variable_, variable).value()]; + return lp_reduced_cost_[gtl::FindOrDie(mirror_lp_variable_, variable) + .value()]; } void LinearProgrammingConstraint::UpdateBoundsOfLpVariables() { @@ -250,10 +251,11 @@ bool LinearProgrammingConstraint::Propagate() { std::vector local_solution; for (const IntegerVariable var : generator.vars) { if (VariableIsPositive(var)) { - const auto index = FindOrDie(mirror_lp_variable_, var); + const auto index = gtl::FindOrDie(mirror_lp_variable_, var); local_solution.push_back(GetVariableValueAtCpScale(index)); } else { - const auto index = FindOrDie(mirror_lp_variable_, NegationOf(var)); + const auto index = + gtl::FindOrDie(mirror_lp_variable_, NegationOf(var)); local_solution.push_back(-GetVariableValueAtCpScale(index)); } } @@ -500,8 +502,8 @@ void AddIncomingAndOutgoingCutsIfNeeded( // Add incoming/outgoing cut arcs, compute flow through cuts. for (int i = 0; i < tails.size(); ++i) { - const bool out = ContainsKey(subset, tails[i]); - const bool in = ContainsKey(subset, heads[i]); + const bool out = gtl::ContainsKey(subset, tails[i]); + const bool in = gtl::ContainsKey(subset, heads[i]); if (out && in) continue; if (out) { sum_outgoing += lp_solution[i]; @@ -527,7 +529,7 @@ void AddIncomingAndOutgoingCutsIfNeeded( int optional_loop_out = -1; for (int i = 0; i < tails.size(); ++i) { if (tails[i] != heads[i]) continue; - if (ContainsKey(subset, tails[i])) { + if (gtl::ContainsKey(subset, tails[i])) { num_optional_nodes_in++; if (optional_loop_in == -1 || lp_solution[i] < lp_solution[optional_loop_in]) { diff --git a/ortools/sat/linear_programming_constraint.h b/ortools/sat/linear_programming_constraint.h index 61d07f8615..81bafc2521 100644 --- a/ortools/sat/linear_programming_constraint.h +++ b/ortools/sat/linear_programming_constraint.h @@ -42,11 +42,11 @@ struct LinearConstraint { std::string DebugString() const { std::string result; const double kInfinity = std::numeric_limits::infinity(); - if (lb != -kInfinity) StrAppend(&result, lb, " <= "); + if (lb != -kInfinity) absl::StrAppend(&result, lb, " <= "); for (int i = 0; i < vars.size(); ++i) { - StrAppend(&result, coeffs[i], "*[", vars[i].value(), "] "); + absl::StrAppend(&result, coeffs[i], "*[", vars[i].value(), "] "); } - if (ub != kInfinity) StrAppend(&result, "<= ", ub); + if (ub != kInfinity) absl::StrAppend(&result, "<= ", ub); return result; } }; diff --git a/ortools/sat/linear_relaxation.cc b/ortools/sat/linear_relaxation.cc index 8103cc831c..38e58f8d3c 100644 --- a/ortools/sat/linear_relaxation.cc +++ b/ortools/sat/linear_relaxation.cc @@ -61,7 +61,7 @@ std::pair GetMinAndMaxNotEncoded( IntegerValue min = kMaxIntegerValue; for (const ClosedInterval interval : (*domains)[var]) { for (IntegerValue v(interval.start); v <= interval.end; ++v) { - if (!ContainsKey(encoded_values, v)) { + if (!gtl::ContainsKey(encoded_values, v)) { min = v; break; } @@ -72,7 +72,7 @@ std::pair GetMinAndMaxNotEncoded( IntegerValue max = kMinIntegerValue; for (const ClosedInterval interval : gtl::reversed_view((*domains)[var])) { for (IntegerValue v(interval.end); v >= interval.start; --v) { - if (!ContainsKey(encoded_values, v)) { + if (!gtl::ContainsKey(encoded_values, v)) { max = v; break; } diff --git a/ortools/sat/model.h b/ortools/sat/model.h index faf3e6337d..7983e4f6fd 100644 --- a/ortools/sat/model.h +++ b/ortools/sat/model.h @@ -81,15 +81,15 @@ class Model { // TODO(user): Rename to GetOrCreateSingleton(). template T* GetOrCreate() { - const size_t type_id = FastTypeId(); - if (!ContainsKey(singletons_, type_id)) { + const size_t type_id = gtl::FastTypeId(); + if (!gtl::ContainsKey(singletons_, type_id)) { // TODO(user): directly store std::unique_ptr<> in singletons_? T* new_t = MyNew(0); singletons_[type_id] = new_t; TakeOwnership(new_t); return new_t; } - return static_cast(FindOrDie(singletons_, type_id)); + return static_cast(gtl::FindOrDie(singletons_, type_id)); } // Likes GetOrCreate() but do not create the object if it is non-existing. @@ -97,14 +97,14 @@ class Model { template const T* Get() const { return static_cast( - FindWithDefault(singletons_, FastTypeId(), nullptr)); + gtl::FindWithDefault(singletons_, gtl::FastTypeId(), nullptr)); } // Same as Get(), but returns a mutable version of the object. template T* Mutable() const { return static_cast( - FindWithDefault(singletons_, FastTypeId(), nullptr)); + gtl::FindWithDefault(singletons_, gtl::FastTypeId(), nullptr)); } // Gives ownership of a pointer to this model. diff --git a/ortools/sat/optimization.cc b/ortools/sat/optimization.cc index b6b4576f74..ae0ba0848a 100644 --- a/ortools/sat/optimization.cc +++ b/ortools/sat/optimization.cc @@ -1214,7 +1214,7 @@ SatSolver::Status FindCores(std::vector assumptions, int new_size = 0; std::set temp(core.begin(), core.end()); for (int i = 0; i < assumptions.size(); ++i) { - if (ContainsKey(temp, assumptions[i])) continue; + if (gtl::ContainsKey(temp, assumptions[i])) continue; assumptions[new_size++] = assumptions[i]; } assumptions.resize(new_size); @@ -1489,8 +1489,8 @@ SatSolver::Status MinimizeWithCoreAndLazyEncoding( for (int i = 0; i < integer_assumptions.size(); ++i) { assumptions.push_back(integer_encoder->GetOrCreateAssociatedLiteral( integer_assumptions[i])); - InsertOrDie(&assumption_to_term_index, assumptions.back().Index(), - term_indices[i]); + gtl::InsertOrDie(&assumption_to_term_index, assumptions.back().Index(), + term_indices[i]); } // Solve under the assumptions. @@ -1527,7 +1527,7 @@ SatSolver::Status MinimizeWithCoreAndLazyEncoding( IntegerValue new_var_ub(0); int new_depth = 0; for (const Literal lit : core) { - const int index = FindOrDie(assumption_to_term_index, lit.Index()); + const int index = gtl::FindOrDie(assumption_to_term_index, lit.Index()); min_weight = std::min(min_weight, terms[index].weight); max_weight = std::max(max_weight, terms[index].weight); new_depth = std::max(new_depth, terms[index].depth + 1); @@ -1564,7 +1564,8 @@ SatSolver::Status MinimizeWithCoreAndLazyEncoding( std::vector constraint_vars; std::vector constraint_coeffs; for (const Literal lit : core) { - const int index = FindOrDie(assumption_to_term_index, lit.Index()); + const int index = + gtl::FindOrDie(assumption_to_term_index, lit.Index()); terms[index].weight -= min_weight; constraint_vars.push_back(terms[index].var); constraint_coeffs.push_back(1); @@ -1726,7 +1727,7 @@ SatSolver::Status MinimizeWithHittingSetAndLazyEncoding( } else { assumptions.push_back(integer_encoder->GetOrCreateAssociatedLiteral( IntegerLiteral::LowerOrEqual(variables[i], hs_value))); - InsertOrDie(&assumption_to_index, assumptions.back().Index(), i); + gtl::InsertOrDie(&assumption_to_index, assumptions.back().Index(), i); } } @@ -1766,7 +1767,8 @@ SatSolver::Status MinimizeWithHittingSetAndLazyEncoding( sat_solver->SetAssumptionLevel(0); for (const std::vector& core : cores) { if (core.size() == 1) { - const int index = FindOrDie(assumption_to_index, core.front().Index()); + const int index = + gtl::FindOrDie(assumption_to_index, core.front().Index()); hs_model.mutable_variable(index)->set_lower_bound( integer_trail->LowerBound(variables[index]).value()); continue; @@ -1776,7 +1778,7 @@ SatSolver::Status MinimizeWithHittingSetAndLazyEncoding( MPConstraintProto* ct = hs_model.add_constraint(); ct->set_lower_bound(1.0); for (const Literal lit : core) { - const int index = FindOrDie(assumption_to_index, lit.Index()); + const int index = gtl::FindOrDie(assumption_to_index, lit.Index()); const double lb = integer_trail->LowerBound(variables[index]).value(); const double hs_value = response.variable_value(index); if (hs_value == lb) { @@ -1785,7 +1787,7 @@ SatSolver::Status MinimizeWithHittingSetAndLazyEncoding( ct->set_lower_bound(ct->lower_bound() + lb); } else { const std::pair key = {index, hs_value}; - if (!ContainsKey(created_var, key)) { + if (!gtl::ContainsKey(created_var, key)) { const int new_var_index = hs_model.variable_size(); created_var[key] = new_var_index; @@ -1803,7 +1805,7 @@ SatSolver::Status MinimizeWithHittingSetAndLazyEncoding( implication->add_var_index(new_var_index); implication->add_coefficient(lb - hs_value - 1); } - ct->add_var_index(FindOrDieNoPrint(created_var, key)); + ct->add_var_index(gtl::FindOrDieNoPrint(created_var, key)); ct->add_coefficient(1.0); } } diff --git a/ortools/sat/precedences.cc b/ortools/sat/precedences.cc index f16d0f837d..a08746709c 100644 --- a/ortools/sat/precedences.cc +++ b/ortools/sat/precedences.cc @@ -31,20 +31,6 @@ bool IsInvalidOrTrue(LiteralIndex index, const Trail& trail) { trail.Assignment().LiteralIsTrue(Literal(index)); } -void AppendNegationIfValid(LiteralIndex i, std::vector* reason) { - if (i != kNoLiteralIndex) reason->push_back(Literal(i).Negated()); -} - -void AppendNegationIfValidAndAssigned(LiteralIndex i, const Trail& trail, - std::vector* reason) { - if (i != kNoLiteralIndex) { - DCHECK(!trail.Assignment().LiteralIsFalse(Literal(i))); - if (trail.Assignment().LiteralIsTrue(Literal(i))) { - reason->push_back(Literal(i).Negated()); - } - } -} - void AppendLowerBoundReasonIfValid(IntegerVariable var, const IntegerTrail& i_trail, std::vector* reason) { @@ -60,30 +46,25 @@ bool PrecedencesPropagator::Propagate(Trail* trail) { return Propagate(); } bool PrecedencesPropagator::Propagate() { while (propagation_trail_index_ < trail_->Index()) { const Literal literal = (*trail_)[propagation_trail_index_++]; - - if (literal.Index() < potential_nodes_.size()) { - // We need to mark these nodes since they are now "present". - for (const int node : potential_nodes_[literal.Index()]) { - const IntegerVariable i(node); - modified_vars_.Set(i); - modified_vars_.Set(NegationOf(i)); - } - } - - if (literal.Index() >= potential_arcs_.size()) continue; + if (literal.Index() >= literal_to_new_impacted_arcs_.size()) continue; // IMPORTANT: Because of the way Untrail() work, we need to add all the // potential arcs before we can abort. It is why we iterate twice here. - for (const int arc_index : potential_arcs_[literal.Index()]) { - const ArcInfo& arc = arcs_[arc_index]; - impacted_arcs_[arc.tail_var].push_back(arc_index); + for (const ArcIndex arc_index : + literal_to_new_impacted_arcs_[literal.Index()]) { + if (--arc_counts_[arc_index] == 0) { + const ArcInfo& arc = arcs_[arc_index]; + impacted_arcs_[arc.tail_var].push_back(arc_index); + } } // Iterate again to check for a propagation and indirectly update // modified_vars_. - for (const int arc_index : potential_arcs_[literal.Index()]) { + for (const ArcIndex arc_index : + literal_to_new_impacted_arcs_[literal.Index()]) { + if (arc_counts_[arc_index] > 0) continue; const ArcInfo& arc = arcs_[arc_index]; - if (!ArcShouldPropagate(arc, *trail_)) continue; + if (integer_trail_->IsCurrentlyIgnored(arc.head_var)) continue; const IntegerValue new_head_lb = integer_trail_->LowerBound(arc.tail_var) + ArcOffset(arc); if (new_head_lb > integer_trail_->LowerBound(arc.head_var)) { @@ -95,9 +76,14 @@ bool PrecedencesPropagator::Propagate() { // Do the actual propagation of the IntegerVariable bounds. InitializeBFQueueWithModifiedNodes(); if (!BellmanFordTarjan(trail_)) return false; - DCHECK(NoPropagationLeft(*trail_)); - // Propagate the presence literal of the arcs that can't be added. + // We can only test that no propagation is left if we didn't enqueue new + // literal in the presence of optional variables. + if (propagation_trail_index_ == trail_->Index()) { + DCHECK(NoPropagationLeft(*trail_)); + } + + // Propagate the presence literals of the arcs that can't be added. PropagateOptionalArcs(trail_); // Clean-up modified_vars_ to do as little as possible on the next call. @@ -105,6 +91,19 @@ bool PrecedencesPropagator::Propagate() { return true; } +bool PrecedencesPropagator::PropagateOutgoingArcs(IntegerVariable var) { + for (const ArcIndex arc_index : impacted_arcs_[var]) { + const ArcInfo& arc = arcs_[arc_index]; + if (integer_trail_->IsCurrentlyIgnored(arc.head_var)) continue; + const IntegerValue new_head_lb = + integer_trail_->LowerBound(arc.tail_var) + ArcOffset(arc); + if (new_head_lb > integer_trail_->LowerBound(arc.head_var)) { + if (!EnqueueAndCheck(arc, new_head_lb, trail_)) return false; + } + } + return true; +} + void PrecedencesPropagator::Untrail(const Trail& trail, int trail_index) { if (propagation_trail_index_ > trail_index) { // This means that we already propagated all there is to propagate @@ -114,10 +113,13 @@ void PrecedencesPropagator::Untrail(const Trail& trail, int trail_index) { } while (propagation_trail_index_ > trail_index) { const Literal literal = trail[--propagation_trail_index_]; - if (literal.Index() >= potential_arcs_.size()) continue; - for (const int arc_index : potential_arcs_[literal.Index()]) { - const ArcInfo& arc = arcs_[arc_index]; - impacted_arcs_[arc.tail_var].pop_back(); + if (literal.Index() >= literal_to_new_impacted_arcs_.size()) continue; + for (const ArcIndex arc_index : + literal_to_new_impacted_arcs_[literal.Index()]) { + if (arc_counts_[arc_index]++ == 0) { + const ArcInfo& arc = arcs_[arc_index]; + impacted_arcs_[arc.tail_var].pop_back(); + } } } } @@ -136,8 +138,9 @@ void PrecedencesPropagator::ComputePrecedences( const IntegerVariable var = vars[index]; CHECK_NE(kNoIntegerVariable, var); if (!to_consider[index] || var >= impacted_arcs_.size()) continue; - for (const int i : impacted_arcs_[var]) { - const ArcInfo& arc = arcs_[i]; + for (const ArcIndex arc_index : impacted_arcs_[var]) { + const ArcInfo& arc = arcs_[arc_index]; + if (integer_trail_->IsCurrentlyIgnored(arc.head_var)) continue; IntegerValue min_offset = arc.offset; if (arc.offset_var != kNoIntegerVariable) { @@ -160,7 +163,7 @@ void PrecedencesPropagator::ComputePrecedences( } var_to_last_index_[arc.head_var] = index; var_to_degree_[arc.head_var]++; - tmp_precedences_.push_back({index, arc.head_var, arc.presence_l}); + tmp_precedences_.push_back({index, arc.head_var, arc.presence_literals}); } } @@ -202,7 +205,6 @@ void PrecedencesPropagator::AdjustSizeFor(IntegerVariable i) { for (IntegerVariable var(impacted_arcs_.size()); var <= index; ++var) { watcher_->WatchLowerBound(var, watcher_id_); } - optional_literals_.resize(index + 1, kNoLiteralIndex); impacted_arcs_.resize(index + 1); impacted_potential_arcs_.resize(index + 1); var_to_degree_.resize(index + 1); @@ -210,60 +212,55 @@ void PrecedencesPropagator::AdjustSizeFor(IntegerVariable i) { } } -void PrecedencesPropagator::MarkIntegerVariableAsOptional(IntegerVariable i, - Literal is_present) { - optional_literals_[i] = is_present.Index(); - optional_literals_[NegationOf(i)] = is_present.Index(); - if (is_present.Index() >= potential_nodes_.size()) { - potential_nodes_.resize(is_present.Index().value() + 1); - } - potential_nodes_[is_present.Index()].push_back(i.value()); -} - void PrecedencesPropagator::AddArc(IntegerVariable tail, IntegerVariable head, IntegerValue offset, - IntegerVariable offset_var, LiteralIndex l) { + IntegerVariable offset_var, + LiteralIndex presence_literal_index) { + DCHECK_EQ(trail_->CurrentDecisionLevel(), 0); AdjustSizeFor(tail); AdjustSizeFor(head); if (offset_var != kNoIntegerVariable) AdjustSizeFor(offset_var); - // Deal with optional variables. - // TODO(user): the code would be a lot simpler if instead, for each arc, we - // tweak the literal controlling the arc presence. - if (integer_trail_->IsOptional(tail) && - optional_literals_[tail] == kNoLiteralIndex) { - MarkIntegerVariableAsOptional( - tail, integer_trail_->IsIgnoredLiteral(tail).Negated()); - } - if (integer_trail_->IsOptional(head) && - optional_literals_[head] == kNoLiteralIndex) { - MarkIntegerVariableAsOptional( - head, integer_trail_->IsIgnoredLiteral(head).Negated()); - } - - // Handle level zero stuff. - DCHECK_EQ(trail_->CurrentDecisionLevel(), 0); - if (l != kNoLiteralIndex) { - // Check if the conditional literal is already fixed. - if (trail_->Assignment().LiteralIsTrue(Literal(l))) { - l = kNoLiteralIndex; // At true, same as fixed arc. - } else if (trail_->Assignment().LiteralIsFalse(Literal(l))) { - return; // At false, nothing to add. + // This arc is present iff all the literals here are true. + absl::InlinedVector enforcement_literals; + { + if (presence_literal_index != kNoLiteralIndex) { + enforcement_literals.push_back(Literal(presence_literal_index)); } + if (integer_trail_->IsOptional(tail)) { + enforcement_literals.push_back( + integer_trail_->IsIgnoredLiteral(tail).Negated()); + } + if (integer_trail_->IsOptional(head)) { + enforcement_literals.push_back( + integer_trail_->IsIgnoredLiteral(head).Negated()); + } + if (offset_var != kNoIntegerVariable && + integer_trail_->IsOptional(offset_var)) { + enforcement_literals.push_back( + integer_trail_->IsIgnoredLiteral(offset_var).Negated()); + } + gtl::STLSortAndRemoveDuplicates(&enforcement_literals); + int new_size = 0; + for (const Literal l : enforcement_literals) { + if (trail_->Assignment().LiteralIsTrue(Literal(l))) { + continue; // At true, ignore this literal. + } else if (trail_->Assignment().LiteralIsFalse(Literal(l))) { + return; // At false, ignore completely this arc. + } + enforcement_literals[new_size++] = l; + } + enforcement_literals.resize(new_size); } if (head == tail) { // A self-arc is either plain SAT or plain UNSAT or it forces something on - // the given offset_var or l. In any case it could be presolved in something - // more efficent. + // the given offset_var or presence_literal_index. In any case it could be + // presolved in something more efficent. VLOG(1) << "Self arc! This could be presolved. " << "var:" << tail << " offset:" << offset - << " offset_var:" << offset_var << " conditioned_by:" << l; - if (offset_var == kNoIntegerVariable) { - // Always false => l is false, otherwise this is a no op. - if (offset > 0) trail_->EnqueueWithUnitReason(Literal(l).Negated()); - return; - } + << " offset_var:" << offset_var + << " conditioned_by:" << presence_literal_index; } // Remove the offset_var if it is fixed. @@ -276,39 +273,40 @@ void PrecedencesPropagator::AddArc(IntegerVariable tail, IntegerVariable head, } } - if (l != kNoLiteralIndex && l.value() >= potential_arcs_.size()) { - potential_arcs_.resize(l.value() + 1); + // Deal first with impacted_potential_arcs_/potential_arcs_. + if (!enforcement_literals.empty()) { + const OptionalArcIndex arc_index(potential_arcs_.size()); + potential_arcs_.push_back( + {tail, head, offset, offset_var, enforcement_literals}); + impacted_potential_arcs_[tail].push_back(arc_index); + impacted_potential_arcs_[NegationOf(head)].push_back(arc_index); + if (offset_var != kNoIntegerVariable) { + impacted_potential_arcs_[offset_var].push_back(arc_index); + } } + // Now deal with impacted_arcs_/arcs_. struct InternalArc { IntegerVariable tail_var; IntegerVariable head_var; IntegerVariable offset_var; - - // Optimization: impacted_potential_arcs_ is only used by - // PropagateOptionalArcs() to detect when the literal l can be propagated to - // false. Because of how this function works, we only need to add one arc - // per tail_var in the code below. - bool add_to_impacted_potential_arcs; }; - std::vector to_add; if (offset_var == kNoIntegerVariable) { // a + offset <= b and -b + offset <= -a - to_add.push_back({tail, head, kNoIntegerVariable, true}); - to_add.push_back( - {NegationOf(head), NegationOf(tail), kNoIntegerVariable, true}); + to_add.push_back({tail, head, kNoIntegerVariable}); + to_add.push_back({NegationOf(head), NegationOf(tail), kNoIntegerVariable}); } else { // tail (a) and offset_var (b) are symmetric, so we add: // - a + b + offset <= c - to_add.push_back({tail, head, offset_var, true}); - to_add.push_back({offset_var, head, tail, true}); + to_add.push_back({tail, head, offset_var}); + to_add.push_back({offset_var, head, tail}); // - a - c + offset <= -b - to_add.push_back({tail, NegationOf(offset_var), NegationOf(head), false}); - to_add.push_back({NegationOf(head), NegationOf(offset_var), tail, true}); + to_add.push_back({tail, NegationOf(offset_var), NegationOf(head)}); + to_add.push_back({NegationOf(head), NegationOf(offset_var), tail}); // - b - c + offset <= -a - to_add.push_back({offset_var, NegationOf(tail), NegationOf(head), false}); - to_add.push_back({NegationOf(head), NegationOf(tail), offset_var, false}); + to_add.push_back({offset_var, NegationOf(tail), NegationOf(head)}); + to_add.push_back({NegationOf(head), NegationOf(tail), offset_var}); } for (const InternalArc a : to_add) { // Since we add a new arc, we will need to consider its tail during the next @@ -326,30 +324,37 @@ void PrecedencesPropagator::AddArc(IntegerVariable tail, IntegerVariable head, // a.head_var and let the normal "is modified" mecanism handle any eventual // follow up propagations. modified_vars_.Set(a.tail_var); - const int arc_index = arcs_.size(); - if (l == kNoLiteralIndex) { + + // If a.head_var is optional, we can potentially remove some literal from + // enforcement_literals. + const ArcIndex arc_index(arcs_.size()); + arcs_.push_back( + {a.tail_var, a.head_var, offset, a.offset_var, enforcement_literals}); + auto& presence_literals = arcs_.back().presence_literals; + if (integer_trail_->IsOptional(a.head_var)) { + // TODO(user): More generally, we can remove any literal that is implied + // by to_remove. + const Literal to_remove = + integer_trail_->IsIgnoredLiteral(a.head_var).Negated(); + const auto it = std::find(presence_literals.begin(), + presence_literals.end(), to_remove); + if (it != presence_literals.end()) presence_literals.erase(it); + } + + if (presence_literals.empty()) { impacted_arcs_[a.tail_var].push_back(arc_index); } else { - if (a.add_to_impacted_potential_arcs) { - impacted_potential_arcs_[a.tail_var].push_back(arc_index); + for (const Literal l : presence_literals) { + if (l.Index() >= literal_to_new_impacted_arcs_.size()) { + literal_to_new_impacted_arcs_.resize(l.Index().value() + 1); + } + literal_to_new_impacted_arcs_[l.Index()].push_back(arc_index); } - potential_arcs_[l].push_back(arc_index); } - arcs_.push_back({a.tail_var, a.head_var, offset, a.offset_var, l}); + arc_counts_.push_back(presence_literals.size()); } } -bool PrecedencesPropagator::ArcShouldPropagate(const ArcInfo& arc, - const Trail& trail) const { - if (integer_trail_->IsCurrentlyIgnored(arc.head_var)) return false; - - const LiteralIndex index = OptionalLiteralOf(arc.tail_var); - if (index == kNoLiteralIndex) return true; - if (trail.Assignment().LiteralIsFalse(Literal(index))) return false; - return trail.Assignment().LiteralIsTrue(Literal(index)) || - index == OptionalLiteralOf(arc.head_var); -} - // TODO(user): On jobshop problems with a lot of tasks per machine (500), this // takes up a big chunck of the running time even before we find a solution. // This is because, for each lower bound changed, we inspect 500 arcs even @@ -359,31 +364,24 @@ void PrecedencesPropagator::PropagateOptionalArcs(Trail* trail) { for (const IntegerVariable var : modified_vars_.PositionsSetAtLeastOnce()) { if (var >= impacted_potential_arcs_.size()) break; - // We can't deduce anything if this is the case. - if (!IsInvalidOrTrue(OptionalLiteralOf(var), *trail)) continue; - - // Note that we can currently do the same computation up to 3 times: - // - if tail_var changed. - // - if NegationOf(head_var) changed, we will process the "reverse" arc, - // but it will lead to the same computation and the same presence literal - // to be propagated. - // - if offset_var changed. - const IntegerValue tail_lb = integer_trail_->LowerBound(var); - for (const int arc_index : impacted_potential_arcs_[var]) { - const ArcInfo& arc = arcs_[arc_index]; - const Literal is_present(arc.presence_l); - if (trail->Assignment().VariableIsAssigned(is_present.Variable())) { - continue; + // Note that we can currently check the same ArcInfo up to 3 times, one for + // each of the arc variables: tail, NegationOf(head) and offset_var. + for (const OptionalArcIndex arc_index : impacted_potential_arcs_[var]) { + const ArcInfo& arc = potential_arcs_[arc_index]; + int num_not_true = 0; + Literal to_propagate; + for (const Literal l : arc.presence_literals) { + if (!trail->Assignment().LiteralIsTrue(l)) { + ++num_not_true; + to_propagate = l; + } } + if (num_not_true != 1) continue; + if (trail->Assignment().LiteralIsFalse(to_propagate)) continue; - // We can't deduce anything if the head node is optional and unassigned. - if (!IsInvalidOrTrue(OptionalLiteralOf(arc.head_var), *trail)) { - continue; - } - - // We want the other bound of head to test infeasibility of the head - // IntegerVariable. - DCHECK_EQ(var, arc.tail_var); + // Test if this arc can be present or not. + // Important arc.tail_var can be different from var here. + const IntegerValue tail_lb = integer_trail_->LowerBound(arc.tail_var); const IntegerValue head_ub = integer_trail_->UpperBound(arc.head_var); if (tail_lb + ArcOffset(arc) > head_ub) { integer_reason_.clear(); @@ -394,11 +392,10 @@ void PrecedencesPropagator::PropagateOptionalArcs(Trail* trail) { AppendLowerBoundReasonIfValid(arc.offset_var, *integer_trail_, &integer_reason_); literal_reason_.clear(); - AppendNegationIfValid(OptionalLiteralOf(arc.tail_var), - &literal_reason_); - AppendNegationIfValid(OptionalLiteralOf(arc.head_var), - &literal_reason_); - integer_trail_->EnqueueLiteral(is_present.Negated(), literal_reason_, + for (const Literal l : arc.presence_literals) { + if (l != to_propagate) literal_reason_.push_back(l.Negated()); + } + integer_trail_->EnqueueLiteral(to_propagate.Negated(), literal_reason_, integer_reason_); } } @@ -417,22 +414,20 @@ bool PrecedencesPropagator::EnqueueAndCheck(const ArcInfo& arc, DCHECK_GT(new_head_lb, integer_trail_->LowerBound(arc.head_var)); // Compute the reason for new_head_lb. + // + // TODO(user): do like for clause and keep the negation of + // arc.presence_literals? I think we could change the integer.h API to accept + // true literal like for IntegerVariable, it is really confusing currently. literal_reason_.clear(); - AppendNegationIfValid(arc.presence_l, &literal_reason_); - AppendNegationIfValidAndAssigned(OptionalLiteralOf(arc.tail_var), *trail, - &literal_reason_); + for (const Literal l : arc.presence_literals) { + literal_reason_.push_back(l.Negated()); + } integer_reason_.clear(); integer_reason_.push_back(integer_trail_->LowerBoundAsLiteral(arc.tail_var)); AppendLowerBoundReasonIfValid(arc.offset_var, *integer_trail_, &integer_reason_); - // Propagate. - // - // Subtle: we need Enqueue() to still propagate a bound of an optional - // variable that we know cannot be present. We need this so that: - // 1. Our sparse cleaning algo in CleanUpMarkedArcsAndParents() works. - // 2. NoPropagationLeft() is happy too. return integer_trail_->Enqueue( IntegerLiteral::GreaterOrEqual(arc.head_var, new_head_lb), literal_reason_, integer_reason_); @@ -441,9 +436,9 @@ bool PrecedencesPropagator::EnqueueAndCheck(const ArcInfo& arc, bool PrecedencesPropagator::NoPropagationLeft(const Trail& trail) const { const int num_nodes = impacted_arcs_.size(); for (IntegerVariable var(0); var < num_nodes; ++var) { - for (const int index : impacted_arcs_[var]) { - const ArcInfo& arc = arcs_[index]; - if (!ArcShouldPropagate(arc, trail)) continue; + for (const ArcIndex arc_index : impacted_arcs_[var]) { + const ArcInfo& arc = arcs_[arc_index]; + if (integer_trail_->IsCurrentlyIgnored(arc.head_var)) continue; if (integer_trail_->LowerBound(arc.tail_var) + ArcOffset(arc) > integer_trail_->LowerBound(arc.head_var)) { return false; @@ -475,7 +470,7 @@ void PrecedencesPropagator::CleanUpMarkedArcsAndParents() { const int num_nodes = impacted_arcs_.size(); for (const IntegerVariable var : modified_vars_.PositionsSetAtLeastOnce()) { if (var >= num_nodes) continue; - const int parent_arc_index = bf_parent_arc_of_[var.value()]; + const ArcIndex parent_arc_index = bf_parent_arc_of_[var.value()]; if (parent_arc_index != -1) { arcs_[parent_arc_index].is_marked = false; bf_parent_arc_of_[var.value()] = -1; @@ -483,7 +478,7 @@ void PrecedencesPropagator::CleanUpMarkedArcsAndParents() { } } DCHECK(std::none_of(bf_parent_arc_of_.begin(), bf_parent_arc_of_.end(), - [](int v) { return v != -1; })); + [](ArcIndex v) { return v != -1; })); DCHECK(std::none_of(bf_can_be_skipped_.begin(), bf_can_be_skipped_.end(), [](bool v) { return v; })); } @@ -497,7 +492,7 @@ bool PrecedencesPropagator::DisassembleSubtree( while (!tmp_vector_.empty()) { const int tail = tmp_vector_.back(); tmp_vector_.pop_back(); - for (const int arc_index : impacted_arcs_[IntegerVariable(tail)]) { + for (const ArcIndex arc_index : impacted_arcs_[IntegerVariable(tail)]) { const ArcInfo& arc = arcs_[arc_index]; if (arc.is_marked) { arc.is_marked = false; // mutable. @@ -514,11 +509,14 @@ bool PrecedencesPropagator::DisassembleSubtree( // Note(user): because of our "special" graph, we can't just follow the // bf_parent_arc_of_[] to reconstruct the cycle, this is because given an arc, // we don't know if it was impacted by its tail or by it offset_var (if not -// equal to kNoIntegerVariable). +// equal to kNoIntegerVariable). Actually, this is now no longer the case +// because we have duplicate arcs depending on the source that caused +// propagation! // // Our solution is to walk again the forward graph using a DFS to reconstruct // the arcs that form a positive cycle. -void PrecedencesPropagator::ReportPositiveCycle(int first_arc, Trail* trail) { +void PrecedencesPropagator::ReportPositiveCycle(ArcIndex first_arc, + Trail* trail) { // TODO(user): I am not sure we have a theoretical guarantee than the // set of arcs appearing in bf_parent_arc_of_[] form a tree here because // we consider all of them, not just the marked ones. Because of that, @@ -529,12 +527,12 @@ void PrecedencesPropagator::ReportPositiveCycle(int first_arc, Trail* trail) { tmp_vector_.clear(); tmp_vector_.push_back(first_node); in_queue[first_node] = true; - std::vector arc_queue{first_arc}; - std::vector arc_on_cycle; + std::vector arc_queue{first_arc}; + std::vector arc_on_cycle; bool found = false; while (!found && !tmp_vector_.empty()) { const int node = tmp_vector_.back(); - const int incoming_arc = arc_queue.back(); + const ArcIndex incoming_arc = arc_queue.back(); if (node == -1) { // We are coming back up in the tree. tmp_vector_.pop_back(); @@ -546,7 +544,7 @@ void PrecedencesPropagator::ReportPositiveCycle(int first_arc, Trail* trail) { // We are going down in the tree. tmp_vector_.back() = -1; // Mark as explored. arc_on_cycle.push_back(incoming_arc); - for (const int arc_index : impacted_arcs_[IntegerVariable(node)]) { + for (const ArcIndex arc_index : impacted_arcs_[IntegerVariable(node)]) { if (arc_index == first_arc) { // The cycle is complete. found = true; @@ -573,16 +571,23 @@ void PrecedencesPropagator::ReportPositiveCycle(int first_arc, Trail* trail) { integer_reason_.clear(); conflict->clear(); IntegerValue sum(0); - for (const int arc_index : arc_on_cycle) { + for (const ArcIndex arc_index : arc_on_cycle) { const ArcInfo& arc = arcs_[arc_index]; sum += ArcOffset(arc); AppendLowerBoundReasonIfValid(arc.offset_var, *integer_trail_, &integer_reason_); - AppendNegationIfValid(arc.presence_l, conflict); - - // On a cycle, all the optional integer should necessarily be present. - CHECK(IsInvalidOrTrue(OptionalLiteralOf(arc.tail_var), *trail)); - AppendNegationIfValid(OptionalLiteralOf(arc.tail_var), conflict); + if (integer_trail_->IsOptional(arc.head_var)) { + // TODO(user): We don't deal with the case where the cycle is between + // optional variable that are not present (hence the CHECK below). For + // now, we never encountered this in practice. We could fix the code, but + // it is a bit involved. + const Literal l = integer_trail_->IsIgnoredLiteral(arc.head_var); + CHECK(trail_->Assignment().LiteralIsFalse(l)); + conflict->push_back(l); + } + for (const Literal l : arc.presence_literals) { + conflict->push_back(l.Negated()); + } } integer_trail_->MergeReasonInto(integer_reason_, conflict); @@ -592,7 +597,7 @@ void PrecedencesPropagator::ReportPositiveCycle(int first_arc, Trail* trail) { // We don't want any duplicates. // TODO(user): I think we could handle them, so maybe this is not needed. - STLSortAndRemoveDuplicates(conflict); + gtl::STLSortAndRemoveDuplicates(conflict); } // Note that in our settings it is important to use an algorithm that tries to @@ -605,7 +610,7 @@ bool PrecedencesPropagator::BellmanFordTarjan(Trail* trail) { // These vector are reset by CleanUpMarkedArcsAndParents() so resize is ok. bf_can_be_skipped_.resize(num_nodes, false); - bf_parent_arc_of_.resize(num_nodes, -1); + bf_parent_arc_of_.resize(num_nodes, ArcIndex(-1)); const auto cleanup = ::operations_research::util::MakeCleanup([this]() { CleanUpMarkedArcsAndParents(); }); @@ -629,16 +634,14 @@ bool PrecedencesPropagator::BellmanFordTarjan(Trail* trail) { continue; } - // Note that while this look like a graph traversal, it is slightly trickier - // because we may iterate on arcs without the same tail here (when the node - // appear as an offset_var). The algo should still work fine though. - for (const int arc_index : impacted_arcs_[IntegerVariable(node)]) { + const IntegerValue tail_lb = + integer_trail_->LowerBound(IntegerVariable(node)); + for (const ArcIndex arc_index : impacted_arcs_[IntegerVariable(node)]) { const ArcInfo& arc = arcs_[arc_index]; - if (!ArcShouldPropagate(arc, *trail)) continue; - - const IntegerValue candidate = - integer_trail_->LowerBound(arc.tail_var) + ArcOffset(arc); + DCHECK_EQ(arc.tail_var, node); + const IntegerValue candidate = tail_lb + ArcOffset(arc); if (candidate > integer_trail_->LowerBound(arc.head_var)) { + if (integer_trail_->IsCurrentlyIgnored(arc.head_var)) continue; if (!EnqueueAndCheck(arc, candidate, trail)) return false; // This is the Tarjan contribution to Bellman-Ford. This code detect @@ -692,24 +695,19 @@ void PrecedencesPropagator::AddGreaterThanAtLeastOneOfConstraints( SatSolver* solver = model->GetOrCreate(); // Fill the set of incoming conditional arcs for each variables. - ITIVector> incoming_arcs_; - for (int i = 0; i < arcs_.size(); ++i) { - const ArcInfo& arc = arcs_[i]; + ITIVector> incoming_arcs_; + for (ArcIndex arc_index(0); arc_index < arcs_.size(); ++arc_index) { + const ArcInfo& arc = arcs_[arc_index]; - // Only keep arc whose presence is unknown and that have a fixed offset. - // We also don't deal with optional tail variable. + // Only keep arc that have a fixed offset and a single presence_literals. if (arc.offset_var != kNoIntegerVariable) continue; if (arc.tail_var == arc.head_var) continue; - if (OptionalLiteralOf(arc.tail_var) != kNoLiteralIndex) continue; - if (arc.presence_l == kNoLiteralIndex) continue; - if (solver->Assignment().LiteralIsAssigned(Literal(arc.presence_l))) { - continue; - } + if (arc.presence_literals.size() != 1) continue; if (arc.head_var >= incoming_arcs_.size()) { incoming_arcs_.resize(arc.head_var.value() + 1); } - incoming_arcs_[arc.head_var].push_back(i); + incoming_arcs_[arc.head_var].push_back(arc_index); } int num_added_constraints = 0; @@ -721,9 +719,10 @@ void PrecedencesPropagator::AddGreaterThanAtLeastOneOfConstraints( // TODO(user): call MinimizeCoreWithPropagation() on the clause. solver->Backtrack(0); std::vector clause; - for (const int a : incoming_arcs_[target]) { - const Literal literal(arcs_[a].presence_l); + for (const ArcIndex arc_index : incoming_arcs_[target]) { + const Literal literal = arcs_[arc_index].presence_literals.front(); if (solver->Assignment().LiteralIsFalse(literal)) continue; + const int old_level = solver->CurrentDecisionLevel(); solver->EnqueueDecisionAndBacktrackOnConflict(literal.Negated()); const int new_level = solver->CurrentDecisionLevel(); @@ -737,11 +736,11 @@ void PrecedencesPropagator::AddGreaterThanAtLeastOneOfConstraints( if (clause.size() > 1) { // Extract the set of arc for which at least one must be present. const std::set clause_set(clause.begin(), clause.end()); - std::vector arcs_in_clause; - for (const int a : incoming_arcs_[target]) { - const Literal literal(arcs_[a].presence_l); - if (ContainsKey(clause_set, literal.Negated())) { - arcs_in_clause.push_back(a); + std::vector arcs_in_clause; + for (const ArcIndex arc_index : incoming_arcs_[target]) { + const Literal literal(arcs_[arc_index].presence_literals.front()); + if (gtl::ContainsKey(clause_set, literal.Negated())) { + arcs_in_clause.push_back(arc_index); } } @@ -751,10 +750,10 @@ void PrecedencesPropagator::AddGreaterThanAtLeastOneOfConstraints( std::vector vars; std::vector offsets; std::vector selectors; - for (const int a : arcs_in_clause) { + for (const ArcIndex a : arcs_in_clause) { vars.push_back(arcs_[a].tail_var); offsets.push_back(arcs_[a].offset); - selectors.push_back(Literal(arcs_[a].presence_l)); + selectors.push_back(Literal(arcs_[a].presence_literals.front())); } model->Add(GreaterThanAtLeastOneOf(target, vars, offsets, selectors)); solver->Propagate(); diff --git a/ortools/sat/precedences.h b/ortools/sat/precedences.h index 1cb7c30b64..5d4bb6d0dc 100644 --- a/ortools/sat/precedences.h +++ b/ortools/sat/precedences.h @@ -60,10 +60,21 @@ class PrecedencesPropagator : public SatPropagator, PropagatorInterface { bool Propagate(Trail* trail) final; void Untrail(const Trail& trail, int trail_index) final; + // Propagates all the outgoing arcs of the given variable (and only those). It + // is more efficient to do all these propagation in one go by calling + // Propagate(), but for scheduling problem, we wants to propagate right away + // the end of an interval when its start moved. + bool PropagateOutgoingArcs(IntegerVariable var); + // Add a precedence relation (i1 + offset <= i2) between integer variables. + // + // Important: The optionality of the variable should be marked BEFORE this + // is called. void AddPrecedence(IntegerVariable i1, IntegerVariable i2); void AddPrecedenceWithOffset(IntegerVariable i1, IntegerVariable i2, IntegerValue offset); + void AddPrecedenceWithVariableOffset(IntegerVariable i1, IntegerVariable i2, + IntegerVariable offset_var); // Same as above, but the relation is only true when the given literal is. void AddConditionalPrecedence(IntegerVariable i1, IntegerVariable i2, @@ -72,18 +83,6 @@ class PrecedencesPropagator : public SatPropagator, PropagatorInterface { IntegerVariable i2, IntegerValue offset, Literal l); - // Note that we currently do not support marking a variable appearing as - // an offset_var as optional (with MarkIntegerVariableAsOptional()). We could - // give it a meaning (like the arcs are not propagated if it is optional), but - // the code currently do not implement this. - // - // TODO(user): support optional offset_var? - // - // TODO(user): the variable offset should probably be tested more because - // when I wrote this, I just had a couple of problems to test this on. - void AddPrecedenceWithVariableOffset(IntegerVariable i1, IntegerVariable i2, - IntegerVariable offset_var); - // Generic function that cover all of the above case and more. void AddPrecedenceWithAllOptions(IntegerVariable i1, IntegerVariable i2, IntegerValue offset, @@ -107,7 +106,9 @@ class PrecedencesPropagator : public SatPropagator, PropagatorInterface { struct IntegerPrecedences { int index; // in vars. IntegerVariable var; // An IntegerVariable that is >= to vars[index]. - LiteralIndex reason; // The reason for it to be >= or kNoLiteralIndex. + + // The reason for it to be >=. + absl::InlinedVector reason; // Only needed for testing. bool operator==(const IntegerPrecedences& o) const { @@ -130,6 +131,9 @@ class PrecedencesPropagator : public SatPropagator, PropagatorInterface { void AddGreaterThanAtLeastOneOfConstraints(Model* model); private: + DEFINE_INT_TYPE(ArcIndex, int); + DEFINE_INT_TYPE(OptionalArcIndex, int); + // Information about an individual arc. struct ArcInfo { IntegerVariable tail_var; @@ -137,29 +141,15 @@ class PrecedencesPropagator : public SatPropagator, PropagatorInterface { IntegerValue offset; IntegerVariable offset_var; // kNoIntegerVariable if none. - LiteralIndex presence_l; // kNoLiteralIndex if none. + + // This arc is "present" iff all these literals are true. + absl::InlinedVector presence_literals; // Used temporarily by our implementation of the Bellman-Ford algorithm. It // should be false at the beginning of BellmanFordTarjan(). mutable bool is_marked; }; - // An optional integer variable has a special behavior: - // - If the bounds on i cross each other, then is_present must be false. - // - It will only propagate any outgoing arcs if is_present is true. - // - // TODO(user): Accept a BinaryImplicationGraph* here, so that and arc - // (tail -> head) can still propagate if tail.is_present => head.is_present. - // Note that such propagation is only useful if the status of tail presence - // is still undecided. Note that we do propagate if tail and head have the - // same presence literal (see ArcShouldPropagate()). - // - // TODO(user): use instead integer_trail_->VariableIsOptional()? Note that the - // meaning is not exactly the same, because here we also do not propagate the - // outgoing arcs. And we need to watch the is_present variable, so we still - // need to call this function. - void MarkIntegerVariableAsOptional(IntegerVariable i, Literal is_present); - // Internal functions to add new precedence relations. // // Note that internally, we only propagate lower bounds, so each time we add @@ -169,24 +159,12 @@ class PrecedencesPropagator : public SatPropagator, PropagatorInterface { void AddArc(IntegerVariable tail, IntegerVariable head, IntegerValue offset, IntegerVariable offset_var, LiteralIndex l); - // Helper function for a slightly more readable code. - LiteralIndex OptionalLiteralOf(IntegerVariable var) const { - return optional_literals_[var]; - } - // Enqueue a new lower bound for the variable arc.head_lb that was deduced // from the current value of arc.tail_lb and the offset of this arc. bool EnqueueAndCheck(const ArcInfo& arc, IntegerValue new_head_lb, Trail* trail); IntegerValue ArcOffset(const ArcInfo& arc) const; - // Returns true iff this arc should propagate. For now, this is true when: - // - tail node is non-optional - // - tail node is optional and present. - // - tail node is optional, its presence is unknown, and its presence literal - // is the same as the one of head. - bool ArcShouldPropagate(const ArcInfo& arc, const Trail& trail) const; - // Inspect all the optional arcs that needs inspection (to stay sparse) and // check if their presence literal can be propagated to false. void PropagateOptionalArcs(Trail* trail); @@ -211,7 +189,7 @@ class PrecedencesPropagator : public SatPropagator, PropagatorInterface { bool BellmanFordTarjan(Trail* trail); bool DisassembleSubtree(int source, int target, std::vector* can_be_skipped); - void ReportPositiveCycle(int first_arc, Trail* trail); + void ReportPositiveCycle(ArcIndex first_arc, Trail* trail); void CleanUpMarkedArcsAndParents(); // Loops over all the arcs and verify that there is no propagation left. @@ -230,19 +208,25 @@ class PrecedencesPropagator : public SatPropagator, PropagatorInterface { // IntegerVariable that changed since the last clear. SparseBitset modified_vars_; - // An arc needs to be inspected for propagation (i.e. is impacted) if: - // - Its tail_var changed. - // - Its offset_var changed. + // An arc needs to be inspected for propagation (i.e. is impacted) if its + // tail_var changed. If an arc has 3 variables (tail, offset, head), it will + // appear as 6 different entries in the arcs_ vector, one for each variable + // and its negation, each time with a different tail. // - // All the int are arc indices in the arcs_ vector. + // TODO(user): rearranging the index so that the arc of the same node are + // consecutive like in StaticGraph should have a big performance impact. // - // The first vector (impacted_arcs_) correspond to the arc currently present - // whereas the second vector (impacted_potential_arcs_) list all the potential - // arcs (the one not always present) and is just used for propagation of the - // arc presence literals. - ITIVector> impacted_arcs_; - ITIVector> + // TODO(user): We do not need to store ArcInfo.tail_var here. + ITIVector> impacted_arcs_; + ITIVector arcs_; + + // This is similar to impacted_arcs_/arcs_ but it is only used to propagate + // one of the presence literals when the arc cannot be present. An arc needs + // to appear only once in potential_arcs_, but it will be referenced by + // all its variable in impacted_potential_arcs_. + ITIVector> impacted_potential_arcs_; + ITIVector potential_arcs_; // Temporary vectors used by ComputePrecedences(). ITIVector var_to_degree_; @@ -257,19 +241,16 @@ class PrecedencesPropagator : public SatPropagator, PropagatorInterface { std::vector tmp_sorted_vars_; std::vector tmp_precedences_; - // The set of arcs that must be added to impacted_arcs_ when a literal become - // true. - ITIVector> potential_arcs_; - - // Used for MarkIntegerVariableAsOptional(). The nodes associated to an - // IntegerVariable whose entry is not kNoLiteralIndex will only propagate - // something to its neighbors if the coresponding literal is assigned to true. - ITIVector optional_literals_; - ITIVector> potential_nodes_; - - // TODO(user): rearranging the index so that the arc of the same node are - // consecutive like in StaticGraph should have a big performance impact. - std::vector arcs_; + // Each time a literal becomes true, this list the set of arcs for which we + // need to decrement their count. When an arc count reach zero, it must be + // added to the set of impacted_arcs_. Note that counts never becomes + // negative. + // + // TODO(user): Try a one-watcher approach instead. Note that in most cases + // arc should be controlled by 1 or 2 literals, so not sure it is worth it. + ITIVector> + literal_to_new_impacted_arcs_; + ITIVector arc_counts_; // Temp vectors to hold the reason of an assignment. std::vector literal_reason_; @@ -281,7 +262,7 @@ class PrecedencesPropagator : public SatPropagator, PropagatorInterface { std::deque bf_queue_; std::vector bf_in_queue_; std::vector bf_can_be_skipped_; - std::vector bf_parent_arc_of_; + std::vector bf_parent_arc_of_; // Temp vector used by the tree traversal in DisassembleSubtree(). std::vector tmp_vector_; diff --git a/ortools/sat/sat_solver.cc b/ortools/sat/sat_solver.cc index 90be8742fc..2c8b988fd0 100644 --- a/ortools/sat/sat_solver.cc +++ b/ortools/sat/sat_solver.cc @@ -1148,7 +1148,13 @@ SatSolver::Status SatSolver::SolveInternal(TimeLimit* time_limit) { parameters_->minimize_with_propagation_restart_period(); MinimizeSomeClauses( parameters_->minimize_with_propagation_num_decisions()); - if (is_model_unsat_) return MODEL_UNSAT; + + // Corner case: the minimization above being based on propagation may + // fix the remaining variables or prove UNSAT. + if (is_model_unsat_) return StatusWithLog(MODEL_UNSAT); + if (trail_->Index() == num_variables_.value()) { + return StatusWithLog(MODEL_SAT); + } } DCHECK_GE(CurrentDecisionLevel(), assumption_level_); diff --git a/ortools/sat/simplification.cc b/ortools/sat/simplification.cc index d9b7a1f2e4..e58ce46b79 100644 --- a/ortools/sat/simplification.cc +++ b/ortools/sat/simplification.cc @@ -269,7 +269,7 @@ void SatPresolver::LoadProblemIntoSatSolver(SatSolver* solver) { temp.push_back(Literal(mapping[l.Variable()], l.IsPositive())); } if (!temp.empty()) solver->AddProblemClause(temp); - STLClearObject(&clause_ref); + gtl::STLClearObject(&clause_ref); } } @@ -589,7 +589,7 @@ void SatPresolver::RemoveAndRegisterForPostsolveAllClauseContaining(Literal x) { for (ClauseIndex i : literal_to_clauses_[x.Index()]) { if (!clauses_[i].empty()) RemoveAndRegisterForPostsolve(i, x); } - STLClearObject(&literal_to_clauses_[x.Index()]); + gtl::STLClearObject(&literal_to_clauses_[x.Index()]); literal_to_clause_sizes_[x.Index()] = 0; } @@ -693,7 +693,7 @@ void SatPresolver::Remove(ClauseIndex ci) { if (drat_writer_ != nullptr) { drat_writer_->DeleteClause(clauses_[ci]); } - STLClearObject(&clauses_[ci]); + gtl::STLClearObject(&clauses_[ci]); } void SatPresolver::RemoveAndRegisterForPostsolve(ClauseIndex ci, Literal x) { diff --git a/ortools/sat/table.cc b/ortools/sat/table.cc index 91fa91f351..59dd0a797d 100644 --- a/ortools/sat/table.cc +++ b/ortools/sat/table.cc @@ -91,11 +91,11 @@ void ProcessOneColumn( // is false too (i.e not possible). for (int i = 0; i < values.size(); ++i) { const IntegerValue v = values[i]; - if (!ContainsKey(encoding, v)) { + if (!gtl::ContainsKey(encoding, v)) { model->Add(ClauseConstraint({line_literals[i].Negated()})); } else { value_to_list_of_line_literals[v].push_back(line_literals[i]); - model->Add(Implication(FindOrDie(encoding, v).Negated(), + model->Add(Implication(gtl::FindOrDie(encoding, v).Negated(), line_literals[i].Negated())); } } @@ -104,7 +104,7 @@ void ProcessOneColumn( // false too. for (const auto& entry : value_to_list_of_line_literals) { std::vector clause = entry.second; - clause.push_back(FindOrDie(encoding, entry.first).Negated()); + clause.push_back(gtl::FindOrDie(encoding, entry.first).Negated()); model->Add(ClauseConstraint(clause)); } } @@ -140,7 +140,7 @@ std::function TableConstraint( for (const std::vector& tuple : tuples) { bool keep = true; for (int i = 0; i < n; ++i) { - if (!ContainsKey(values_per_var[i], tuple[i])) { + if (!gtl::ContainsKey(values_per_var[i], tuple[i])) { keep = false; break; } @@ -202,8 +202,8 @@ std::function NegatedTableConstraint( for (const std::vector& tuple : tuples) { bool add_tuple = true; for (int i = 0; i < n; ++i) { - if (ContainsKey(mapping[i], tuple[i])) { - clause[i] = FindOrDie(mapping[i], tuple[i]).Negated(); + if (gtl::ContainsKey(mapping[i], tuple[i])) { + clause[i] = gtl::FindOrDie(mapping[i], tuple[i]).Negated(); } else { add_tuple = false; break; @@ -311,7 +311,7 @@ std::function TransitionConstraint( for (const std::vector& transition : automata) { CHECK_EQ(transition.size(), 3); const std::pair p{transition[0], transition[1]}; - CHECK(!ContainsKey(unique_transition_checker, p)) + CHECK(!gtl::ContainsKey(unique_transition_checker, p)) << "Duplicate outgoing transitions with value " << transition[1] << " from state " << transition[0] << "."; unique_transition_checker.insert(p); @@ -341,8 +341,8 @@ std::function TransitionConstraint( // all the possible transitions. for (int time = 0; time + 1 < n; ++time) { for (const std::vector& transition : automata) { - if (!ContainsKey(reachable_states[time], transition[0])) continue; - if (!ContainsKey(possible_values[time], transition[1])) continue; + if (!gtl::ContainsKey(reachable_states[time], transition[0])) continue; + if (!gtl::ContainsKey(possible_values[time], transition[1])) continue; reachable_states[time + 1].insert(transition[2]); } } @@ -351,9 +351,10 @@ std::function TransitionConstraint( for (int time = n - 1; time > 0; --time) { std::set new_set; for (const std::vector& transition : automata) { - if (!ContainsKey(reachable_states[time], transition[0])) continue; - if (!ContainsKey(possible_values[time], transition[1])) continue; - if (!ContainsKey(reachable_states[time + 1], transition[2])) continue; + if (!gtl::ContainsKey(reachable_states[time], transition[0])) continue; + if (!gtl::ContainsKey(possible_values[time], transition[1])) continue; + if (!gtl::ContainsKey(reachable_states[time + 1], transition[2])) + continue; new_set.insert(transition[0]); } reachable_states[time].swap(new_set); @@ -376,9 +377,10 @@ std::function TransitionConstraint( std::vector transition_values; std::vector out_states; for (const std::vector& transition : automata) { - if (!ContainsKey(reachable_states[time], transition[0])) continue; - if (!ContainsKey(possible_values[time], transition[1])) continue; - if (!ContainsKey(reachable_states[time + 1], transition[2])) continue; + if (!gtl::ContainsKey(reachable_states[time], transition[0])) continue; + if (!gtl::ContainsKey(possible_values[time], transition[1])) continue; + if (!gtl::ContainsKey(reachable_states[time + 1], transition[2])) + continue; // TODO(user): if this transition correspond to just one in-state or // one-out state or one variable value, we could reuse the corresponding @@ -398,7 +400,7 @@ std::function TransitionConstraint( // Fully instantiate vars[time]. { std::vector s = transition_values; - STLSortAndRemoveDuplicates(&s); + gtl::STLSortAndRemoveDuplicates(&s); encoding.clear(); if (s.size() > 1) { @@ -423,7 +425,7 @@ std::function TransitionConstraint( // propagation. { std::vector s = out_states; - STLSortAndRemoveDuplicates(&s); + gtl::STLSortAndRemoveDuplicates(&s); out_encoding.clear(); std::vector state_literals; diff --git a/ortools/sat/timetable.cc b/ortools/sat/timetable.cc index 3fae931616..1c1b527a8c 100644 --- a/ortools/sat/timetable.cc +++ b/ortools/sat/timetable.cc @@ -36,12 +36,13 @@ TimeTablingPerTask::TimeTablingPerTask( // the profile is shaped like the Hanoi tower. The additional space is for // both extremities and the sentinels. profile_.reserve(2 * num_tasks_ + 4); - scp_.reserve(num_tasks_); - ecp_.reserve(num_tasks_); // Reversible set of tasks to consider for propagation. - num_tasks_to_sweep_ = num_tasks_; - tasks_to_sweep_.resize(num_tasks_); + forward_num_tasks_to_sweep_ = num_tasks_; + forward_tasks_to_sweep_.resize(num_tasks_); + backward_num_tasks_to_sweep_ = num_tasks_; + backward_tasks_to_sweep_.resize(num_tasks_); + num_active_tasks_ = num_tasks_; active_tasks_.resize(num_tasks_); num_profile_tasks_ = 0; @@ -60,7 +61,8 @@ TimeTablingPerTask::TimeTablingPerTask( by_end_min_.resize(num_tasks_); for (int t = 0; t < num_tasks_; ++t) { - tasks_to_sweep_[t] = t; + forward_tasks_to_sweep_[t] = t; + backward_tasks_to_sweep_[t] = t; active_tasks_[t] = t; profile_tasks_[t] = t; positions_in_profile_tasks_[t] = t; @@ -86,7 +88,8 @@ bool TimeTablingPerTask::Propagate() { // if (num_tasks_to_sweep_ == 0) return true; // Save the current state of the set of tasks. - rev_repository_int_.SaveState(&num_tasks_to_sweep_); + rev_repository_int_.SaveState(&forward_num_tasks_to_sweep_); + rev_repository_int_.SaveState(&backward_num_tasks_to_sweep_); rev_repository_int_.SaveState(&num_active_tasks_); rev_repository_int_.SaveState(&num_profile_tasks_); @@ -97,11 +100,11 @@ bool TimeTablingPerTask::Propagate() { // This can fail if the profile exceeds the resource capacity. if (!BuildProfile()) return false; // Update the minimum start times. - if (!SweepAllTasks()) return false; + if (!SweepAllTasks(/*is_forward=*/true)) return false; // We reuse the same profile, but reversed, to update the maximum end times. ReverseProfile(); // Update the maximum end times (reversed problem). - if (!SweepAllTasks()) return false; + if (!SweepAllTasks(/*is_forward=*/false)) return false; } // Reduce the profile now that we know that it is stable. @@ -138,13 +141,6 @@ bool TimeTablingPerTask::BuildProfile() { // Likely to be already or almost sorted. IncrementalSort(by_start_max_.begin() + left_start_, by_start_max_.begin() + right_start_); - // Build start of compulsory part events. - scp_.clear(); - for (int i = left_start_; i < right_start_; ++i) { - if (IsInProfile(by_start_max_[i].task_index)) { - scp_.push_back(by_start_max_[i]); - } - } // Update end value of active tasks. for (int i = left_end_; i < right_end_; ++i) { @@ -153,13 +149,6 @@ bool TimeTablingPerTask::BuildProfile() { // Likely to be already or almost sorted. IncrementalSort(by_end_min_.begin() + left_end_, by_end_min_.begin() + right_end_); - // Build end of compulsory part events. - ecp_.clear(); - for (int i = left_end_; i < right_end_; ++i) { - if (IsInProfile(by_end_min_[i].task_index)) { - ecp_.push_back(by_end_min_[i]); - } - } // Build the profile. // ------------------ @@ -170,41 +159,41 @@ bool TimeTablingPerTask::BuildProfile() { IntegerValue max_height_start = kMinIntegerValue; // Add a sentinel to simplify the algorithm. - profile_.push_back( - ProfileRectangle(kMinIntegerValue, kMinIntegerValue, IntegerValue(0))); + profile_.emplace_back(kMinIntegerValue, IntegerValue(0)); // Start and height of the currently built profile rectange. IntegerValue current_start = kMinIntegerValue; IntegerValue current_height = starting_profile_height_; - // Next scp and ecp events to be processed. - int next_scp = 0; - int next_ecp = 0; - - while (next_ecp < ecp_.size()) { + // Next start/end of the compulsory parts to be processed. Note that only the + // task for which IsInProfile() is true must be considered. + int next_start = left_start_; + int next_end = left_end_; + while (next_end < right_end_) { const IntegerValue old_height = current_height; - // Next time point. - IntegerValue t = ecp_[next_ecp].time; - if (next_scp < scp_.size()) { - t = std::min(t, scp_[next_scp].time); + IntegerValue t = by_end_min_[next_end].time; + if (next_start < right_start_) { + t = std::min(t, by_start_max_[next_start].time); } // Process the starting compulsory parts. - while (next_scp < scp_.size() && scp_[next_scp].time == t) { - current_height += DemandMin(scp_[next_scp].task_index); - next_scp++; + while (next_start < right_start_ && by_start_max_[next_start].time == t) { + const int task_index = by_start_max_[next_start].task_index; + if (IsInProfile(task_index)) current_height += DemandMin(task_index); + ++next_start; } // Process the ending compulsory parts. - while (next_ecp < ecp_.size() && ecp_[next_ecp].time == t) { - current_height -= DemandMin(ecp_[next_ecp].task_index); - next_ecp++; + while (next_end < right_end_ && by_end_min_[next_end].time == t) { + const int task_index = by_end_min_[next_end].task_index; + if (IsInProfile(task_index)) current_height -= DemandMin(task_index); + ++next_end; } // Insert a new profile rectangle if any. if (current_height != old_height) { - profile_.push_back(ProfileRectangle(current_start, t, old_height)); + profile_.emplace_back(current_start, old_height); if (current_height > profile_max_height_) { profile_max_height_ = current_height; max_height_start = t; @@ -212,14 +201,13 @@ bool TimeTablingPerTask::BuildProfile() { current_start = t; } } + // Build the last profile rectangle. DCHECK_GE(current_height, 0); - profile_.push_back( - ProfileRectangle(current_start, kMaxIntegerValue, IntegerValue(0))); + profile_.emplace_back(current_start, IntegerValue(0)); // Add a sentinel to simplify the algorithm. - profile_.push_back( - ProfileRectangle(kMaxIntegerValue, kMaxIntegerValue, IntegerValue(0))); + profile_.emplace_back(kMaxIntegerValue, IntegerValue(0)); // Increase the capacity variable if required. return IncreaseCapacity(max_height_start, profile_max_height_); @@ -288,61 +276,56 @@ void TimeTablingPerTask::ReduceProfile() { void TimeTablingPerTask::ReverseProfile() { helper_->SetTimeDirection(false); // backward - // Do not swap sentinels. - int left = 1; - int right = profile_.size() - 2; - // Swap and reverse profile rectangles. - while (left < right) { - IntegerValue tmp = profile_[left].start; - profile_[left].start = -profile_[right].end; - profile_[right].end = -tmp; - tmp = profile_[left].end; - profile_[left].end = -profile_[right].start; - profile_[right].start = -tmp; - - std::swap(profile_[left].height, profile_[right].height); - - left++; - right--; - } - // Reverse the profile rectangle in the middle if any. - if (left == right) { - const IntegerValue tmp = profile_[left].start; - profile_[left].start = -profile_[left].end; - profile_[left].end = -tmp; + // We keep the sentinels inchanged. + for (int i = 1; i + 1 < profile_.size(); ++i) { + profile_[i].start = -profile_[i + 1].start; } + std::reverse(profile_.begin() + 1, profile_.end() - 1); } -bool TimeTablingPerTask::SweepAllTasks() { +bool TimeTablingPerTask::SweepAllTasks(bool is_forward) { // Tasks with a lower or equal demand will not be pushed. - const IntegerValue min_demand = CapSub(CapacityMax(), profile_max_height_); + const IntegerValue demand_threshold = + CapSub(CapacityMax(), profile_max_height_); - for (int i = num_tasks_to_sweep_ - 1; i >= 0; --i) { - const int t = tasks_to_sweep_[i]; - const bool fixed_start = helper_->StartMin(t) == helper_->StartMax(t); - const bool fixed_end = helper_->EndMin(t) == helper_->EndMax(t); - // A task does not have to be considered for propagation in the rest of the - // sub-tree if it is absent or if it is present and respects one of these - // conditions: - // - its start and end variables are fixed; - // - it has a maximum duration of 0; - // - it has a maximum demand of 0; + // Select the correct members depending on the direction. + int& num_tasks = + is_forward ? forward_num_tasks_to_sweep_ : backward_num_tasks_to_sweep_; + std::vector& tasks = + is_forward ? forward_tasks_to_sweep_ : backward_tasks_to_sweep_; + + // TODO(user): On some problem, a big chunk of the time is spend just checking + // these conditions below because it requires indirect memory access to fetch + // the demand/duration/presence/start ... + for (int i = num_tasks - 1; i >= 0; --i) { + const int t = tasks[i]; if (helper_->IsAbsent(t) || - (helper_->IsPresent(t) && - ((fixed_start && fixed_end) || helper_->DurationMax(t) == 0 || - DemandMax(t) == 0))) { - // Remove the task from the set of tasks to sweep. - std::swap(tasks_to_sweep_[i], tasks_to_sweep_[--num_tasks_to_sweep_]); + (helper_->IsPresent(t) && helper_->StartIsFixed(t))) { + // This tasks does not have to be considered for propagation in the rest + // of the sub-tree. Note that StartIsFixed() depends on the time + // direction, it is why we use two lists. + std::swap(tasks[i], tasks[--num_tasks]); continue; } - // A task does not have to be considered for propagation in this particular - // iteration if it respects one of these conditions: - // - it is present and its start variable is fixed; - // - its minimum demand cannot lead to a resource overload; - // - its minimum duration is 0. - if ((helper_->IsPresent(t) && fixed_start) || DemandMin(t) <= min_demand || - helper_->DurationMin(t) == 0) { + + // Skip if demand is too low. + if (DemandMin(t) <= demand_threshold) { + if (DemandMax(t) == 0) { + // We can ignore this task for the rest of the subtree like above. + std::swap(tasks[i], tasks[--num_tasks]); + } + + // This task does not have to be considered for propagation in this + // particular iteration, but maybe it does later. + continue; + } + + // Skip if duration is zero. + if (helper_->DurationMin(t) == 0) { + if (helper_->DurationMax(t) == 0) { + std::swap(tasks[i], tasks[--num_tasks]); + } continue; } @@ -361,10 +344,16 @@ bool TimeTablingPerTask::SweepTask(int task_id) { IntegerValue new_start_min = initial_start_min; IntegerValue new_end_min = initial_end_min; - // Find the profile rectangle that overlpas the minimum start time of task_id. + // Find the profile rectangle that overlaps the minimum start time of task_id. // The sentinel prevents out of bound exceptions. - int rec_id = 1; - while (profile_[rec_id].end <= new_start_min) rec_id++; + DCHECK(is_sorted(profile_.begin(), profile_.end())); + int rec_id = + std::upper_bound(profile_.begin(), profile_.end(), new_start_min, + [&](IntegerValue value, const ProfileRectangle& rect) { + return value < rect.start; + }) - + profile_.begin(); + --rec_id; // A profile rectangle is in conflict with the task if its height exceeds // conflict_height. @@ -388,7 +377,8 @@ bool TimeTablingPerTask::SweepTask(int task_id) { // take care of rebuilding the profile with these possible changes and to // propagate again in order to reach the timetabling consistency or to fail if // the profile exceeds the resource capacity. - for (; profile_[rec_id].start < std::min(start_max, new_end_min); ++rec_id) { + IntegerValue limit = std::min(start_max, new_end_min); + for (; profile_[rec_id].start < limit; ++rec_id) { // If the profile rectangle is not conflicting, go to the next rectangle. if (profile_[rec_id].height <= conflict_height) continue; @@ -396,12 +386,13 @@ bool TimeTablingPerTask::SweepTask(int task_id) { // Compute the next minimum start and end times of task_id. The variables // are not updated yet. - new_start_min = profile_[rec_id].end; + new_start_min = profile_[rec_id + 1].start; // i.e. profile_[rec_id].end if (start_max < new_start_min) { new_start_min = start_max; overload = !IsInProfile(task_id); } new_end_min = std::max(new_end_min, new_start_min + duration_min); + limit = std::min(start_max, new_end_min); if (profile_[rec_id].start < initial_end_min) { last_initial_conflict = std::min(new_start_min, initial_end_min) - 1; @@ -422,7 +413,7 @@ bool TimeTablingPerTask::SweepTask(int task_id) { // the old condition). A solution is to update those vector before calling // ReduceProfile() or to ReduceProfile() directly after BuildProfile() in the // main loop. - profile_changed_ |= true; + profile_changed_ = true; // Explain that the task should be absent or explain the resource overload. if (overload) return OverloadOrRemove(task_id, start_max); @@ -486,7 +477,7 @@ bool TimeTablingPerTask::OverloadOrRemove(int task_id, IntegerValue time) { AddProfileReason(time, time + 1); - // We know that task_id was not part of the profile we it was built. We thus + // We know that task_id was not part of the profile when it was built. We thus // have to add it manualy since it will not be added by AddProfileReason. helper_->AddStartMaxReason(task_id, time); helper_->AddEndMinReason(task_id, time + 1); diff --git a/ortools/sat/timetable.h b/ortools/sat/timetable.h index 7921934026..d08bae78fc 100644 --- a/ortools/sat/timetable.h +++ b/ortools/sat/timetable.h @@ -37,12 +37,18 @@ class TimeTablingPerTask : public PropagatorInterface { void RegisterWith(GenericLiteralWatcher* watcher); private: + // The rectangle will be ordered by start, and the end of each rectangle + // will be equal to the start of the next one. struct ProfileRectangle { /* const */ IntegerValue start; - /* const */ IntegerValue end; /* const */ IntegerValue height; - ProfileRectangle(IntegerValue start, IntegerValue end, IntegerValue height) - : start(start), end(end), height(height) {} + + ProfileRectangle(IntegerValue start, IntegerValue height) + : start(start), height(height) {} + + bool operator<(const ProfileRectangle& other) const { + return start < other.start; + } }; // Builds the profile and increases the lower bound of the capacity @@ -64,7 +70,7 @@ class TimeTablingPerTask : public PropagatorInterface { // Tries to increase the minimum start time of each task according to the // current profile. This function can be called after ReverseProfile() and // ReverseVariables to update the maximum end time of each task. - bool SweepAllTasks(); + bool SweepAllTasks(bool is_forward); // Tries to increase the minimum start time of task_id. bool SweepTask(int task_id); @@ -138,10 +144,6 @@ class TimeTablingPerTask : public PropagatorInterface { int left_end_; int right_end_; - // Start (resp. end) of the compulsory parts used to build the profile. - std::vector scp_; - std::vector ecp_; - // Optimistic profile of the resource consumption over time. std::vector profile_; IntegerValue profile_max_height_; @@ -154,10 +156,14 @@ class TimeTablingPerTask : public PropagatorInterface { // and changed the shape of the profile. bool profile_changed_; - // Reversible set of tasks to consider for propagation. The set contains the - // tasks in the [0, num_tasks_to_sweep_) prefix of tasks_to_sweep_. - std::vector tasks_to_sweep_; - int num_tasks_to_sweep_; + // Reversible sets of tasks to consider for the forward (resp. backward) + // propagation. A task with a fixed start do not need to be considered for the + // forward pass, same for task with fixed end for the backward pass. It is why + // we use two sets. + std::vector forward_tasks_to_sweep_; + std::vector backward_tasks_to_sweep_; + int forward_num_tasks_to_sweep_; + int backward_num_tasks_to_sweep_; // Reversible set of tasks to consider for reducing the profile. The set // contains the [0, num_active_tasks_) prefix of active_tasks_. diff --git a/ortools/sat/util.cc b/ortools/sat/util.cc index eda521ed76..02d581a688 100644 --- a/ortools/sat/util.cc +++ b/ortools/sat/util.cc @@ -45,7 +45,7 @@ int MoveOneUnprocessedLiteralLast(const std::set& processed, int relevant_prefix_size, std::vector* literals) { if (literals->empty()) return -1; - if (!ContainsKey(processed, literals->back().Index())) { + if (!gtl::ContainsKey(processed, literals->back().Index())) { return std::min(relevant_prefix_size, literals->size()); } @@ -60,7 +60,7 @@ int MoveOneUnprocessedLiteralLast(const std::set& processed, int num_not_processed = 0; int target_prefix_size = literals->size() - 1; for (int i = literals->size() - 1; i >= 0; i--) { - if (ContainsKey(processed, (*literals)[i].Index())) { + if (gtl::ContainsKey(processed, (*literals)[i].Index())) { ++num_processed; } else { ++num_not_processed; @@ -73,9 +73,10 @@ int MoveOneUnprocessedLiteralLast(const std::set& processed, // Once a prefix size has been decided, it is always better to // enqueue the literal already processed first. - std::stable_partition( - literals->begin() + target_prefix_size, literals->end(), - [&processed](Literal l) { return ContainsKey(processed, l.Index()); }); + std::stable_partition(literals->begin() + target_prefix_size, literals->end(), + [&processed](Literal l) { + return gtl::ContainsKey(processed, l.Index()); + }); return target_prefix_size; } diff --git a/ortools/util/rev.h b/ortools/util/rev.h index 3ba617e22a..2dfcb7ceaf 100644 --- a/ortools/util/rev.h +++ b/ortools/util/rev.h @@ -121,9 +121,9 @@ class RevMap : ReversibleInterface { void SetLevel(int level) final; int Level() const { return first_op_index_of_next_level_.size(); } - bool ContainsKey(key_type key) const { return ::ContainsKey(map_, key); } + bool ContainsKey(key_type key) const { return gtl::ContainsKey(map_, key); } const mapped_type& FindOrDie(key_type key) const { - return ::FindOrDie(map_, key); + return gtl::FindOrDie(map_, key); } void EraseOrDie(key_type key); diff --git a/ortools/util/stats.cc b/ortools/util/stats.cc index 357b59d634..642b9b21fe 100644 --- a/ortools/util/stats.cc +++ b/ortools/util/stats.cc @@ -52,7 +52,7 @@ std::string Stat::StatString() const { return std::string(name_ + ": " + ValueAsString()); } -StatsGroup::~StatsGroup() { STLDeleteValues(&time_distributions_); } +StatsGroup::~StatsGroup() { gtl::STLDeleteValues(&time_distributions_); } void StatsGroup::Register(Stat* stat) { stats_.push_back(stat); } diff --git a/ortools/util/tuple_set.h b/ortools/util/tuple_set.h index 8a860881c1..6476668bb6 100644 --- a/ortools/util/tuple_set.h +++ b/ortools/util/tuple_set.h @@ -200,9 +200,9 @@ bool IntTupleSet::Data::Contains(const std::vector& candidate) const { return false; } const int64 fingerprint = Fingerprint(candidate); - if (ContainsKey(tuple_fprint_to_index_, fingerprint)) { + if (gtl::ContainsKey(tuple_fprint_to_index_, fingerprint)) { const std::vector& indices = - FindOrDie(tuple_fprint_to_index_, fingerprint); + gtl::FindOrDie(tuple_fprint_to_index_, fingerprint); for (int i = 0; i < indices.size(); ++i) { const int tuple_index = indices[i]; for (int j = 0; j < arity_; ++j) { diff --git a/ortools/util/vector_map.h b/ortools/util/vector_map.h index 37528e37e6..34a2a07e1b 100644 --- a/ortools/util/vector_map.h +++ b/ortools/util/vector_map.h @@ -52,17 +52,21 @@ class VectorMap { } // Will return the index of the element if present, or die otherwise. - int IndexOrDie(const T& element) const { return FindOrDie(map_, element); } + int IndexOrDie(const T& element) const { + return gtl::FindOrDie(map_, element); + } // Returns -1 if the element is not in the vector, or its unique // index if it is. int Index(const T& element) const { - return FindWithDefault(map_, element, -1); + return gtl::FindWithDefault(map_, element, -1); } // TODO(user): explore a int-type version. // Returns wether the element has already been added to the vector-map. - bool Contains(const T& element) const { return ContainsKey(map_, element); } + bool Contains(const T& element) const { + return gtl::ContainsKey(map_, element); + } // Returns the element at position index. const T& Element(int index) const { diff --git a/ortools/util/xml_helper.cc b/ortools/util/xml_helper.cc index 0df8b0bfbb..51979cf2e2 100644 --- a/ortools/util/xml_helper.cc +++ b/ortools/util/xml_helper.cc @@ -40,7 +40,7 @@ void XmlHelper::StartElement(const std::string& name) { } void XmlHelper::AddAttribute(const std::string& key, int value) { - AddAttribute(key, StrCat(value)); + AddAttribute(key, absl::StrCat(value)); } void XmlHelper::AddAttribute(const std::string& key, const std::string& value) {