diff --git a/constraint_solver/constraint_solver.h b/constraint_solver/constraint_solver.h index f3d2d214a6..cf97533b0d 100644 --- a/constraint_solver/constraint_solver.h +++ b/constraint_solver/constraint_solver.h @@ -1516,7 +1516,23 @@ class Solver { // ----- Search Limit ----- - // Limit the search with the 'time', 'branches', 'failures' and + // Creates a search limit that constrains the running time given in + // milliseconds. + SearchLimit* MakeTimeLimit(int64 time_in_ms); + + // Creates a search limit that constrains the number of branches + // explored in the search tree. + SearchLimit* MakeBranchesLimit(int64 branches); + + // Creates a search limit that constrains the number of failures + // that can happen when exploring the search tree. + SearchLimit* MakeFailuresLimit(int64 failures); + + // Creates a search limit that constrains the number of solutions found + // during the search. + SearchLimit* MakeSolutionsLimit(int64 solutions); + + // Limits the search with the 'time', 'branches', 'failures' and // 'solutions' limits. SearchLimit* MakeLimit(int64 time, int64 branches, diff --git a/constraint_solver/constraint_solver.swig b/constraint_solver/constraint_solver.swig index 67255b68af..5c8bf70685 100644 --- a/constraint_solver/constraint_solver.swig +++ b/constraint_solver/constraint_solver.swig @@ -263,6 +263,7 @@ class PyDecisionBuilder(object): %rename (BestValueSolutionCollector) MakeBestValueSolutionCollector; %rename (BetweenCt) MakeBetweenCt; %rename (BoolVar) MakeBoolVar; +%rename (BranchesLimit) MakeBranchesLimit; %rename (ConstantRestart) MakeConstantRestart; %rename (ConvexPiecewiseExpr) MakeConvexPiecewiseExpr; %rename (Count) MakeCount; @@ -273,6 +274,7 @@ class PyDecisionBuilder(object): %rename (Distribute) MakeDistribute; %rename (Element) MakeElement; %rename (FailDecision) MakeFailDecision; +%rename (FailuresLimit) MakeFailuresLimit; %rename (FalseConstraint) MakeFalseConstraint; %rename (FirstSolutionCollector) MakeFirstSolutionCollector; %rename (FixedDurationIntervalVar) MakeFixedDurationIntervalVar; @@ -330,6 +332,7 @@ class PyDecisionBuilder(object): %rename (SemiContinuousExpr) MakeSemiContinuousExpr; %rename (Sequence) MakeSequence; %rename (SimulatedAnnealing) MakeSimulatedAnnealing; +%rename (SolutionsLimit) MakeSolutionsLimit; %rename (SolveOnce) MakeSolveOnce; %rename (SplitVariableDomain) MakeSplitVariableDomain; %rename (StoreAssignment) MakeStoreAssignment; @@ -340,6 +343,7 @@ class PyDecisionBuilder(object): %rename (SymmetryManager) MakeSymmetryManager; %rename (TabuSearch) MakeTabuSearch; %rename (TemporalDisjunction) MakeTemporalDisjunction; +%rename (TimeLimit) MakeTimeLimit; %rename (TransitionConstraint) MakeTransitionConstraint; %rename (TreeMonitor) MakeTreeMonitor; %rename (TrueConstraint) MakeTrueConstraint; @@ -1382,6 +1386,7 @@ struct FailureProtect { %rename (makeBestValueSolutionCollector) operations_research::Solver::MakeBestValueSolutionCollector; %rename (makeBetweenCt) operations_research::Solver::MakeBetweenCt; %rename (makeBoolVar) operations_research::Solver::MakeBoolVar; +%rename (makeBranchesLimit) operations_research::Solver::MakeBranchesLimit; %rename (makeConstantRestart) operations_research::Solver::MakeConstantRestart; %rename (makeConvexPiecewiseExpr) operations_research::Solver::MakeConvexPiecewiseExpr; %rename (makeCount) operations_research::Solver::MakeCount; @@ -1395,6 +1400,7 @@ struct FailureProtect { %rename (makeElement) operations_research::Solver::MakeElement; %rename (makeEquality) operations_research::Solver::MakeEquality; %rename (makeFailDecision) operations_research::Solver::MakeFailDecision; +%rename (makeFailuresLimit) operations_research::Solver::MakeFailuresLimit; %rename (makeFalseConstraint) operations_research::Solver::MakeFalseConstraint; %rename (makeFirstSolutionCollector) operations_research::Solver::MakeFirstSolutionCollector; %rename (makeFixedDurationIntervalVar) operations_research::Solver::MakeFixedDurationIntervalVar; @@ -1469,6 +1475,7 @@ struct FailureProtect { %rename (makeSemiContinuousExpr) operations_research::Solver::MakeSemiContinuousExpr; %rename (makeSequence) operations_research::Solver::MakeSequence; %rename (makeSimulatedAnnealing) operations_research::Solver::MakeSimulatedAnnealing; +%rename (makeSolutionsLimit) operations_research::Solver::MakeSolutionsLimit; %rename (makeSolveOnce) operations_research::Solver::MakeSolveOnce; %rename (makeSplitVariableDomain) operations_research::Solver::MakeSplitVariableDomain; %rename (makeSquare) operations_research::Solver::MakeSquare; @@ -1480,6 +1487,7 @@ struct FailureProtect { %rename (makeSymmetryManager) operations_research::Solver::MakeSymmetryManager; %rename (makeTabuSearch) operations_research::Solver::MakeTabuSearch; %rename (makeTemporalDisjunction) operations_research::Solver::MakeTemporalDisjunction; +%rename (makeTimeLimit) operations_research::Solver::MakeTimeLimit; %rename (makeTransitionConstraint) operations_research::Solver::MakeTransitionConstraint; %rename (makeTreeMonitor) operations_research::Solver::MakeTreeMonitor; %rename (makeTrueConstraint) operations_research::Solver::MakeTrueConstraint; diff --git a/constraint_solver/search.cc b/constraint_solver/search.cc index 53d70c5fd3..012160024c 100644 --- a/constraint_solver/search.cc +++ b/constraint_solver/search.cc @@ -2876,6 +2876,7 @@ class GuidedLocalSearchPenalties { virtual bool HasValues() const = 0; virtual void Increment(const Arc& arc) = 0; virtual int64 Value(const Arc& arc) const = 0; + virtual void Reset() = 0; }; // Dense GLS penalties implementation using a matrix to store penalties. @@ -2886,6 +2887,7 @@ class GuidedLocalSearchPenaltiesTable : public GuidedLocalSearchPenalties { virtual bool HasValues() const { return has_values_; } virtual void Increment(const Arc& arc); virtual int64 Value(const Arc& arc) const; + virtual void Reset(); private: std::vector > penalties_; @@ -2906,6 +2908,13 @@ void GuidedLocalSearchPenaltiesTable::Increment(const Arc& arc) { has_values_ = true; } +void GuidedLocalSearchPenaltiesTable::Reset() { + has_values_ = false; + for (int i = 0; i < penalties_.size(); ++i) { + penalties_[i].clear(); + } +} + int64 GuidedLocalSearchPenaltiesTable::Value(const Arc& arc) const { const std::vector& first_penalties = penalties_[arc.first]; const int64 second = arc.second; @@ -2925,6 +2934,7 @@ class GuidedLocalSearchPenaltiesMap : public GuidedLocalSearchPenalties { virtual bool HasValues() const { return (penalties_.size() != 0); } virtual void Increment(const Arc& arc); virtual int64 Value(const Arc& arc) const; + virtual void Reset(); private: Bitmap penalized_; @@ -2943,6 +2953,11 @@ void GuidedLocalSearchPenaltiesMap::Increment(const Arc& arc) { penalized_.Set(arc.first, true); } +void GuidedLocalSearchPenaltiesMap::Reset() { + penalties_.clear(); + penalized_.Clear(); +} + int64 GuidedLocalSearchPenaltiesMap::Value(const Arc& arc) const { if (penalized_.Get(arc.first)) { return FindWithDefault(penalties_, arc, 0LL); @@ -2963,6 +2978,7 @@ class GuidedLocalSearch : public Metaheuristic { virtual bool AcceptDelta(Assignment* delta, Assignment* deltadelta); virtual void ApplyDecision(Decision* d); virtual bool AtSolution(); + virtual void EnterSearch(); virtual bool LocalOptimum(); virtual int64 AssignmentElementPenalty(const Assignment& assignment, int index) = 0; @@ -3100,6 +3116,16 @@ bool GuidedLocalSearch::AtSolution() { return true; } +void GuidedLocalSearch::EnterSearch() { + Metaheuristic::EnterSearch(); + penalized_objective_ = NULL; + assignment_penalized_value_ = 0; + old_penalized_value_ = 0; + memset(current_penalized_values_.get(), 0, + size_ * sizeof(*current_penalized_values_.get())); + penalties_->Reset(); +} + // GLS filtering; compute the penalized value corresponding to the delta and // modify objective bound accordingly. bool GuidedLocalSearch::AcceptDelta(Assignment* delta, Assignment* deltadelta) { @@ -3708,6 +3734,22 @@ bool RegularLimit::CheckTime() { } } // namespace +SearchLimit* Solver::MakeTimeLimit(int64 time) { + return MakeLimit(time, kint64max, kint64max, kint64max); +} + +SearchLimit* Solver::MakeBranchesLimit(int64 branches) { + return MakeLimit(kint64max, branches, kint64max, kint64max); +} + +SearchLimit* Solver::MakeFailuresLimit(int64 failures) { + return MakeLimit(kint64max, kint64max, failures, kint64max); +} + +SearchLimit* Solver::MakeSolutionsLimit(int64 solutions) { + return MakeLimit(kint64max, kint64max, kint64max, solutions); +} + SearchLimit* Solver::MakeLimit(int64 time, int64 branches, int64 failures, diff --git a/util/const_int_ptr_array.h b/util/const_int_ptr_array.h index 464879e172..776d2df42b 100644 --- a/util/const_int_ptr_array.h +++ b/util/const_int_ptr_array.h @@ -28,6 +28,7 @@ #include "base/stringprintf.h" #include "base/concise_iterator.h" #include "base/map-util.h" +#include "base/hash.h" using std::string; @@ -189,4 +190,3 @@ template class ConstIntPtrArray { }; } // namespace operations_research #endif // OR_TOOLS_UTIL_CONST_INT_PTR_ARRAY_H_ -