diff --git a/ortools/sat/BUILD.bazel b/ortools/sat/BUILD.bazel index a001b6986b..7d8692bd22 100644 --- a/ortools/sat/BUILD.bazel +++ b/ortools/sat/BUILD.bazel @@ -2290,7 +2290,6 @@ cc_test( ":integer_base", ":integer_search", ":intervals", - ":linear_constraint", ":model", ":precedences", ":sat_base", diff --git a/ortools/sat/cumulative_energy_test.cc b/ortools/sat/cumulative_energy_test.cc index 65f316e41c..990f734154 100644 --- a/ortools/sat/cumulative_energy_test.cc +++ b/ortools/sat/cumulative_energy_test.cc @@ -37,7 +37,6 @@ #include "ortools/sat/integer_base.h" #include "ortools/sat/integer_search.h" #include "ortools/sat/intervals.h" -#include "ortools/sat/linear_constraint.h" #include "ortools/sat/model.h" #include "ortools/sat/precedences.h" #include "ortools/sat/sat_base.h" @@ -50,8 +49,6 @@ namespace operations_research { namespace sat { namespace { - /* - // An instance is a set of energy tasks and a capacity. struct EnergyTask { int start_min; @@ -84,31 +81,24 @@ std::string InstanceDebugString(const EnergyInstance& instance) { bool SolveUsingConstraint(const EnergyInstance& instance) { Model model; std::vector intervals; - std::vector> decomposed_energies; + std::vector energy_min; + std::vector energy_max; for (const auto& task : instance.tasks) { + const IntegerVariable start_var = + model.Add(NewIntegerVariable(task.start_min, task.end_max)); + const IntegerVariable end_var = + model.Add(NewIntegerVariable(task.start_min, task.end_max)); + const IntegerVariable size_var = + model.Add(NewIntegerVariable(task.duration_min, task.duration_max)); if (task.is_optional) { const Literal is_present = Literal(model.Add(NewBooleanVariable()), true); - const IntegerVariable start = - model.Add(NewIntegerVariable(task.start_min, task.end_max)); - const IntegerVariable end = - model.Add(NewIntegerVariable(task.start_min, task.end_max)); - const IntegerVariable duration = - model.Add(NewIntegerVariable(task.duration_min, task.duration_max)); - intervals.push_back( - model.Add(NewOptionalInterval(start, end, duration, is_present))); + intervals.push_back(model.Add( + NewOptionalInterval(start_var, end_var, size_var, is_present))); } else { - intervals.push_back(model.Add(NewIntervalWithVariableSize( - task.start_min, task.end_max, task.duration_min, task.duration_max))); + intervals.push_back(model.Add(NewInterval(start_var, end_var, size_var))); } - std::vector energy_literals; - std::vector energy_literals_values_values; - for (int e = task.energy_min; e <= task.energy_max; ++e) { - const Literal lit = Literal(model.Add(NewBooleanVariable()), true); - energy_literals.push_back(lit); - energy_literals_values_values.push_back({lit, e, 1}); - } - model.Add(ExactlyOneConstraint(energy_literals)); - decomposed_energies.push_back(energy_literals_values_values); + energy_min.push_back(task.energy_min); + energy_max.push_back(task.energy_max); } const AffineExpression capacity( @@ -118,7 +108,7 @@ bool SolveUsingConstraint(const EnergyInstance& instance) { SchedulingConstraintHelper* helper = repo->GetOrCreateHelper(intervals); SchedulingDemandHelper* demands_helper = new SchedulingDemandHelper({}, helper, &model); - demands_helper->OverrideDecomposedEnergies(decomposed_energies); + demands_helper->OverrideEnergyBounds(energy_min, energy_max); model.TakeOwnership(demands_helper); AddCumulativeOverloadChecker(capacity, helper, demands_helper, &model); @@ -266,8 +256,6 @@ TEST(CumulativeEnergyTest, CompareToNaiveModel) { } } -*/ - struct CumulativeTasks { int64_t duration; int64_t demand; diff --git a/ortools/sat/integer.h b/ortools/sat/integer.h index 51be1efe29..b0cf07abf9 100644 --- a/ortools/sat/integer.h +++ b/ortools/sat/integer.h @@ -200,7 +200,7 @@ class IntegerEncoder { IntegerValue value) const; // Advanced usage. It is more efficient to create the associated literals in - // order, but it might be anoying to do so. Instead, you can first call + // order, but it might be annoying to do so. Instead, you can first call // DisableImplicationBetweenLiteral() and when you are done creating all the // associated literals, you can call (only at level zero) // AddAllImplicationsBetweenAssociatedLiterals() which will also turn back on @@ -318,7 +318,7 @@ class IntegerEncoder { // corresponding to the same variable). // // Note that we only keep this for positive variable. - // The one for the negation can be infered by it. + // The one for the negation can be inferred by it. // // Like x >= 1 x >= 4 x >= 5 // Correspond to x <= 0 x <= 3 x <= 4 diff --git a/ortools/sat/scheduling_cuts.cc b/ortools/sat/scheduling_cuts.cc index 290a4cf7f0..e5e3575426 100644 --- a/ortools/sat/scheduling_cuts.cc +++ b/ortools/sat/scheduling_cuts.cc @@ -1323,9 +1323,6 @@ CtEvent CopyAndTrimEventAfter(const CtEvent& old_event, IntegerValue time, event.use_energy = event.energy_min > simple_energy_min; } event.x_start_min = time; - event.source.clear(); - event.source.push_back(old_event); - event.trim_date = time; return event; } @@ -1514,10 +1511,6 @@ void GenerateCompletionTimeCutsWithEnergy(absl::string_view cut_name, << "simple_min_shape_area: " << event.energy_min * event.x_size_min; LOG(INFO) << " event = " << event.DebugString(); - if (event.lifted) { - LOG(INFO) << "old_event = " << event.source.front().DebugString(); - LOG(INFO) << " trim_date: " << event.trim_date; - } } CHECK_GE(min_shape_area, event.energy_min * event.x_size_min); diff --git a/ortools/sat/scheduling_cuts.h b/ortools/sat/scheduling_cuts.h index 5c444297a1..5f78d2ca98 100644 --- a/ortools/sat/scheduling_cuts.h +++ b/ortools/sat/scheduling_cuts.h @@ -146,9 +146,6 @@ struct CtEvent : BaseEvent { bool y_size_is_fixed = false; std::string DebugString() const; - - std::vector source; - IntegerValue trim_date = 0; }; // Computes the minimum sum of the end min and the minimum sum of the end min diff --git a/ortools/sat/scheduling_helpers.cc b/ortools/sat/scheduling_helpers.cc index a7791ba3d5..a0012e5635 100644 --- a/ortools/sat/scheduling_helpers.cc +++ b/ortools/sat/scheduling_helpers.cc @@ -799,8 +799,8 @@ bool SchedulingDemandHelper::CacheAllEnergyValues() { return false; } - // Checks the propagation of the consistency of implied values and - // literals. + // Checks the consistency of implied values and literal values with the + // cached bounds of the size and demand expressions. int new_size = 0; IntegerValue min_size = kMaxIntegerValue; IntegerValue max_size = kMinIntegerValue; @@ -838,14 +838,22 @@ bool SchedulingDemandHelper::CacheAllEnergyValues() { } } - cached_energies_min_[t] = - std::max(SimpleEnergyMin(t), DecomposedEnergyMin(t)); + if (t < override_energy_min_.size()) { + cached_energies_min_[t] = override_energy_min_[t]; + } else { + cached_energies_min_[t] = + std::max(SimpleEnergyMin(t), DecomposedEnergyMin(t)); + } if (cached_energies_min_[t] <= kMinIntegerValue) return false; energy_is_quadratic_[t] = decomposed_energies_[t].empty() && !demands_.empty() && !integer_trail_->IsFixed(demands_[t]) && !helper_->SizeIsFixed(t); - cached_energies_max_[t] = - std::min(SimpleEnergyMax(t), DecomposedEnergyMax(t)); + if (t < override_energy_max_.size()) { + cached_energies_max_[t] = override_energy_max_[t]; + } else { + cached_energies_max_[t] = + std::min(SimpleEnergyMax(t), DecomposedEnergyMax(t)); + } if (cached_energies_max_[t] >= kMaxIntegerValue) return false; } diff --git a/ortools/sat/scheduling_helpers.h b/ortools/sat/scheduling_helpers.h index b4353868f8..ea02a2f6e8 100644 --- a/ortools/sat/scheduling_helpers.h +++ b/ortools/sat/scheduling_helpers.h @@ -551,6 +551,12 @@ class SchedulingDemandHelper { // Visible for testing. void OverrideDecomposedEnergies( const std::vector>& energies); + void OverrideEnergyBounds(const std::vector& energy_min, + const std::vector& energy_max) { + override_energy_min_ = energy_min; + override_energy_max_ = energy_max; + } + // Returns the decomposed energy terms compatible with the current literal // assignment. It must not be used to create reasons if not at level 0. // It returns en empty vector if the decomposed energy is not available. @@ -583,6 +589,10 @@ class SchedulingDemandHelper { // A representation of the energies as a set of alternative. // If subvector is empty, we don't have this representation. std::vector> decomposed_energies_; + + // Override energy bounds. + std::vector override_energy_min_; + std::vector override_energy_max_; }; // =============================================================================