diff --git a/ortools/sat/BUILD.bazel b/ortools/sat/BUILD.bazel index 8a7b9563d6..3f40cda1c5 100644 --- a/ortools/sat/BUILD.bazel +++ b/ortools/sat/BUILD.bazel @@ -102,6 +102,7 @@ cc_library( "@com_google_absl//absl/container:btree", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/synchronization", + "@com_google_absl//absl/time", ], ) diff --git a/ortools/sat/cp_model_lns.cc b/ortools/sat/cp_model_lns.cc index 034e33a096..8031a9e4fc 100644 --- a/ortools/sat/cp_model_lns.cc +++ b/ortools/sat/cp_model_lns.cc @@ -205,8 +205,6 @@ void NeighborhoodGeneratorHelper::RecomputeHelperData() { for (int ct_index = 0; ct_index < constraints.size(); ++ct_index) { // We remove the interval constraints since we should have an equivalent // linear constraint somewhere else. - // TODO(user): Fix, the above is not true for a fixed size optional - // interval var. if (constraints[ct_index].constraint_case() == ConstraintProto::kInterval) { continue; } @@ -297,10 +295,6 @@ void NeighborhoodGeneratorHelper::RecomputeHelperData() { // // TODO(user): Exploit connected component while generating fragments. // TODO(user): Do not generate fragment not touching the objective. - const double freq = parameters_.log_frequency_in_seconds(); - absl::Time now = absl::Now(); - if (freq <= 0.0 || now <= last_logging_time_ + absl::Seconds(freq)) return; - std::vector component_sizes; for (const std::vector& component : components_) { component_sizes.push_back(component.size()); @@ -318,12 +312,12 @@ void NeighborhoodGeneratorHelper::RecomputeHelperData() { absl::StrCat(" compo:", absl::StrJoin(component_sizes, ","), ",..."); } } - shared_response_->LogMessage( + shared_response_->LogPeriodicMessage( "Model", absl::StrCat("var:", active_variables_.size(), "/", num_variables, " constraints:", simplied_model_proto_.constraints().size(), - "/", model_proto_.constraints().size(), compo_message)); - last_logging_time_ = now; + "/", model_proto_.constraints().size(), compo_message), + &last_logging_time_); } bool NeighborhoodGeneratorHelper::IsActive(int var) const { diff --git a/ortools/sat/integer_search.cc b/ortools/sat/integer_search.cc index 9a6e48c038..7ffe790e34 100644 --- a/ortools/sat/integer_search.cc +++ b/ortools/sat/integer_search.cc @@ -1300,19 +1300,15 @@ void ContinuousProber::LogStatistics() { shared_bounds_manager_ == nullptr) { return; } - const double freq = parameters_.log_frequency_in_seconds(); - const absl::Time now = absl::Now(); - if (freq <= 0.0 || now <= last_logging_time_ + absl::Seconds(freq)) return; - shared_response_manager_->LogMessage( + shared_response_manager_->LogPeriodicMessage( "Probe", - absl::StrCat( - "#iterations:", iteration_, - " #literals fixed/probed:", prober_->num_new_literals_fixed(), "/", - num_literals_probed_, " #bounds shaved/tried:", num_bounds_shaved_, - "/", num_bounds_tried_, " #new_integer_bounds:", - shared_bounds_manager_->NumBoundsExported("probing"), - ", #new_binary_clauses:", prober_->num_new_binary_clauses())); - last_logging_time_ = now; + absl::StrCat("#iterations:", iteration_, " #literals fixed/probed:", + prober_->num_new_literals_fixed(), "/", num_literals_probed_, + " #bounds shaved/tried:", num_bounds_shaved_, "/", + num_bounds_tried_, " #new_integer_bounds:", + shared_bounds_manager_->NumBoundsExported("probing"), + ", #new_binary_clauses:", prober_->num_new_binary_clauses()), + &last_logging_time_); } } // namespace sat diff --git a/ortools/sat/lb_tree_search.cc b/ortools/sat/lb_tree_search.cc index 927ab5a771..5ed3a095a3 100644 --- a/ortools/sat/lb_tree_search.cc +++ b/ortools/sat/lb_tree_search.cc @@ -371,16 +371,11 @@ SatSolver::Status LbTreeSearch::Search( if (lb > current_objective_lb_) break; } - const absl::Time now = absl::Now(); - if (parameters_.log_frequency_in_seconds() > 0.0 && - now >= last_logging_time_ + - absl::Seconds(parameters_.log_frequency_in_seconds())) { - shared_response_->LogMessage( - "TreeS", absl::StrCat("#nodes:", nodes_.size(), - " #branches:", num_decisions_taken_, - " #imports:", num_imports_)); - last_logging_time_ = now; - } + shared_response_->LogPeriodicMessage( + "TreeS", + absl::StrCat("#nodes:", nodes_.size(), " #branches:", + num_decisions_taken_, " #imports:", num_imports_), + &last_logging_time_); if (n < nodes_.size()) { current_branch_.push_back(n); diff --git a/ortools/sat/synchronization.cc b/ortools/sat/synchronization.cc index ed81dfdcdd..12e8cf9d30 100644 --- a/ortools/sat/synchronization.cc +++ b/ortools/sat/synchronization.cc @@ -16,6 +16,7 @@ #include #include + #if !defined(__PORTABLE_PLATFORM__) #include "ortools/base/file.h" #include "ortools/sat/cp_model_mapping.h" @@ -24,6 +25,7 @@ #include "absl/container/btree_map.h" #include "absl/container/flat_hash_set.h" #include "absl/random/random.h" +#include "absl/time/time.h" #include "ortools/base/integral_types.h" #include "ortools/base/stl_util.h" #include "ortools/sat/cp_model.pb.h" @@ -140,6 +142,23 @@ void SharedResponseManager::LogMessage(const std::string& prefix, wall_timer_.Get(), message)); } +void SharedResponseManager::LogPeriodicMessage(const std::string& prefix, + const std::string& message, + absl::Time* last_logging_time) { + const double freq = parameters_.log_frequency_in_seconds(); + if (freq <= 0.0 || last_logging_time == nullptr) return; + const absl::Time now = absl::Now(); + if (now - *last_logging_time < + absl::Milliseconds(static_cast(freq * 1000))) { + return; + } + *last_logging_time = now; + + absl::MutexLock mutex_lock(&mutex_); + SOLVER_LOG(logger_, absl::StrFormat("#%-5s %6.2fs %s", prefix, + wall_timer_.Get(), message)); +} + void SharedResponseManager::InitializeObjective(const CpModelProto& cp_model) { if (cp_model.has_objective()) { objective_or_null_ = &cp_model.objective(); diff --git a/ortools/sat/synchronization.h b/ortools/sat/synchronization.h index 0a7a5fb89e..dd6244fd06 100644 --- a/ortools/sat/synchronization.h +++ b/ortools/sat/synchronization.h @@ -328,6 +328,8 @@ class SharedResponseManager { void DisplayImprovementStatistics(); void LogMessage(const std::string& prefix, const std::string& message); + void LogPeriodicMessage(const std::string& prefix, const std::string& message, + absl::Time* last_logging_time); // This is here for the few codepath that needs to modify the returned // response directly. Note that this do not work in parallel.