diff --git a/makefiles/Makefile.cpp.mk b/makefiles/Makefile.cpp.mk index 56475dab85..c0355ba8b1 100755 --- a/makefiles/Makefile.cpp.mk +++ b/makefiles/Makefile.cpp.mk @@ -65,7 +65,7 @@ ortoolslibs: $(OR_TOOLS_LIBS) CVRPTW_LIBS = $(LIB_DIR)/$(LIB_PREFIX)cvrptw_lib.$(LIB_SUFFIX) CVRPTW_DEPS = \ $(EX_DIR)/cpp/cvrptw_lib.h \ - $(ROUTING_DEPS) + $(CP_DEPS) $(SRC_DIR)/constraint_solver/routing.h CVRPTW_LNK = $(PRE_LIB)cvrptw_lib$(POST_LIB) $(OR_TOOLS_LNK) cvrptwlibs: $(CVRPTW_LIBS) @@ -156,7 +156,7 @@ ccexe: $(CC_BINARIES) CVRPTW_OBJS=\ $(OBJ_DIR)/cvrptw_lib.$O -$(OBJ_DIR)/cvrptw_lib.$O: $(EX_DIR)/cpp/cvrptw_lib.cc $(EX_DIR)/cpp/cvrptw_lib.h $(ROUTING_DEPS) +$(OBJ_DIR)/cvrptw_lib.$O: $(EX_DIR)/cpp/cvrptw_lib.cc $(EX_DIR)/cpp/cvrptw_lib.h $(CP_DEPS) $(SRC_DIR)/constraint_solver/routing.h $(CCC) $(CFLAGS) -c $(EX_DIR)$Scpp/cvrptw_lib.cc $(OBJ_OUT)$(OBJ_DIR)$Scvrptw_lib.$O $(LIB_DIR)/$(LIB_PREFIX)cvrptw_lib.$(LIB_SUFFIX): $(CVRPTW_OBJS) @@ -435,7 +435,7 @@ $(OBJ_DIR)/nqueens2.$O: $(EX_DIR)/cpp/nqueens2.cc $(CP_DEPS) $(BIN_DIR)/nqueens2$E: $(OR_TOOLS_LIBS) $(OBJ_DIR)/nqueens2.$O $(CCC) $(CFLAGS) $(OBJ_DIR)/nqueens2.$O $(OR_TOOLS_LNK) $(OR_TOOLS_LD_FLAGS) $(EXE_OUT)$(BIN_DIR)$Snqueens2$E -$(OBJ_DIR)/pdptw.$O: $(EX_DIR)/cpp/pdptw.cc $(ROUTING_DEPS) +$(OBJ_DIR)/pdptw.$O: $(EX_DIR)/cpp/pdptw.cc $(CP_DEPS) $(SRC_DIR)/constraint_solver/routing.h $(CCC) $(CFLAGS) -c $(EX_DIR)$Scpp/pdptw.cc $(OBJ_OUT)$(OBJ_DIR)$Spdptw.$O $(BIN_DIR)/pdptw$E: $(OR_TOOLS_LIBS) $(OBJ_DIR)/pdptw.$O @@ -465,7 +465,7 @@ $(OBJ_DIR)/sports_scheduling.$O: $(EX_DIR)/cpp/sports_scheduling.cc $(CP_DEPS) $(BIN_DIR)/sports_scheduling$E: $(OR_TOOLS_LIBS) $(OBJ_DIR)/sports_scheduling.$O $(CCC) $(CFLAGS) $(OBJ_DIR)/sports_scheduling.$O $(OR_TOOLS_LNK) $(OR_TOOLS_LD_FLAGS) $(EXE_OUT)$(BIN_DIR)$Ssports_scheduling$E -$(OBJ_DIR)/tsp.$O: $(EX_DIR)/cpp/tsp.cc $(ROUTING_DEPS) +$(OBJ_DIR)/tsp.$O: $(EX_DIR)/cpp/tsp.cc $(CP_DEPS) $(SRC_DIR)/constraint_solver/routing.h $(CCC) $(CFLAGS) -c $(EX_DIR)$Scpp/tsp.cc $(OBJ_OUT)$(OBJ_DIR)$Stsp.$O $(BIN_DIR)/tsp$E: $(OR_TOOLS_LIBS) $(OBJ_DIR)/tsp.$O diff --git a/makefiles/Makefile.gen.mk b/makefiles/Makefile.gen.mk index 5f907ad86f..fd2a343618 100644 --- a/makefiles/Makefile.gen.mk +++ b/makefiles/Makefile.gen.mk @@ -1227,7 +1227,6 @@ $(OBJ_DIR)/graph/bellman_ford.$O: \ $(OBJ_DIR)/graph/cliques.$O: \ $(SRC_DIR)/graph/cliques.cc \ $(SRC_DIR)/graph/cliques.h \ - $(SRC_DIR)/base/callback.h \ $(SRC_DIR)/base/hash.h $(CCC) $(CFLAGS) -c $(SRC_DIR)/graph/cliques.cc $(OBJ_OUT)$(OBJ_DIR)$Sgraph$Scliques.$O @@ -1264,7 +1263,6 @@ $(OBJ_DIR)/graph/min_cost_flow.$O: \ $(OBJ_DIR)/graph/shortestpaths.$O: \ $(SRC_DIR)/graph/shortestpaths.cc \ $(SRC_DIR)/graph/shortestpaths.h \ - $(SRC_DIR)/base/callback.h \ $(SRC_DIR)/base/casts.h \ $(SRC_DIR)/base/commandlineflags.h \ $(SRC_DIR)/base/hash.h \ @@ -2280,19 +2278,6 @@ $(SRC_DIR)/linear_solver/glop_utils.h: \ $(SRC_DIR)/linear_solver/linear_solver.h \ $(SRC_DIR)/lp_data/lp_types.h -$(SRC_DIR)/linear_solver/linear_expr.h: - -$(SRC_DIR)/linear_solver/linear_solver_ext.h: \ - $(SRC_DIR)/linear_solver/linear_solver.h \ - $(SRC_DIR)/base/commandlineflags.h \ - $(SRC_DIR)/base/hash.h \ - $(SRC_DIR)/base/integral_types.h \ - $(SRC_DIR)/base/logging.h \ - $(SRC_DIR)/base/macros.h \ - $(SRC_DIR)/base/sparsetable.h \ - $(SRC_DIR)/base/strutil.h \ - $(SRC_DIR)/base/timer.h - $(SRC_DIR)/linear_solver/linear_solver.h: \ $(SRC_DIR)/linear_solver/linear_expr.h \ $(GEN_DIR)/linear_solver/linear_solver.pb.h \ @@ -2605,21 +2590,16 @@ $(SRC_DIR)/constraint_solver/constraint_solveri.h: \ $(SRC_DIR)/constraint_solver/hybrid.h: \ $(SRC_DIR)/constraint_solver/constraint_solver.h -$(SRC_DIR)/constraint_solver/routing_flags.h: \ - $(GEN_DIR)/constraint_solver/routing_parameters.pb.h \ - $(SRC_DIR)/base/commandlineflags.h - $(SRC_DIR)/constraint_solver/routing.h: \ $(SRC_DIR)/constraint_solver/constraint_solver.h \ $(SRC_DIR)/constraint_solver/constraint_solveri.h \ $(GEN_DIR)/constraint_solver/routing_parameters.pb.h \ - $(SRC_DIR)/base/adjustable_priority_queue.h \ + $(SRC_DIR)/constraint_solver/routing_types.h \ $(SRC_DIR)/base/adjustable_priority_queue-inl.h \ + $(SRC_DIR)/base/adjustable_priority_queue.h \ $(SRC_DIR)/base/callback.h \ $(SRC_DIR)/base/commandlineflags.h \ $(SRC_DIR)/base/hash.h \ - $(SRC_DIR)/base/integral_types.h \ - $(SRC_DIR)/base/int_type.h \ $(SRC_DIR)/base/int_type_indexed_vector.h \ $(SRC_DIR)/base/logging.h \ $(SRC_DIR)/base/macros.h \ @@ -2627,6 +2607,10 @@ $(SRC_DIR)/constraint_solver/routing.h: \ $(SRC_DIR)/util/sorted_interval_list.h \ $(SRC_DIR)/graph/graph.h +$(SRC_DIR)/constraint_solver/routing_flags.h: \ + $(GEN_DIR)/constraint_solver/routing_parameters.pb.h \ + $(SRC_DIR)/base/commandlineflags.h + $(SRC_DIR)/constraint_solver/routing_neighborhoods.h: \ $(SRC_DIR)/constraint_solver/constraint_solver.h \ $(SRC_DIR)/constraint_solver/constraint_solveri.h \ @@ -2707,16 +2691,6 @@ $(OBJ_DIR)/constraint_solver/collect_variables.$O: \ $(SRC_DIR)/base/stl_util.h $(CCC) $(CFLAGS) -c $(SRC_DIR)/constraint_solver/collect_variables.cc $(OBJ_OUT)$(OBJ_DIR)$Sconstraint_solver$Scollect_variables.$O -$(OBJ_DIR)/constraint_solver/constraints.$O: \ - $(SRC_DIR)/constraint_solver/constraints.cc \ - $(SRC_DIR)/constraint_solver/constraint_solver.h \ - $(SRC_DIR)/constraint_solver/constraint_solveri.h \ - $(SRC_DIR)/base/integral_types.h \ - $(SRC_DIR)/base/logging.h \ - $(SRC_DIR)/util/saturated_arithmetic.h \ - $(SRC_DIR)/util/string_array.h - $(CCC) $(CFLAGS) -c $(SRC_DIR)/constraint_solver/constraints.cc $(OBJ_OUT)$(OBJ_DIR)$Sconstraint_solver$Sconstraints.$O - $(OBJ_DIR)/constraint_solver/constraint_solver.$O: \ $(SRC_DIR)/constraint_solver/constraint_solver.cc \ $(SRC_DIR)/constraint_solver/constraint_solver.h \ @@ -2736,6 +2710,17 @@ $(OBJ_DIR)/constraint_solver/constraint_solver.$O: \ $(SRC_DIR)/util/tuple_set.h $(CCC) $(CFLAGS) -c $(SRC_DIR)/constraint_solver/constraint_solver.cc $(OBJ_OUT)$(OBJ_DIR)$Sconstraint_solver$Sconstraint_solver.$O +$(OBJ_DIR)/constraint_solver/constraints.$O: \ + $(SRC_DIR)/constraint_solver/constraints.cc \ + $(SRC_DIR)/constraint_solver/constraint_solver.h \ + $(SRC_DIR)/constraint_solver/constraint_solveri.h \ + $(SRC_DIR)/base/integral_types.h \ + $(SRC_DIR)/base/join.h \ + $(SRC_DIR)/base/logging.h \ + $(SRC_DIR)/util/saturated_arithmetic.h \ + $(SRC_DIR)/util/string_array.h + $(CCC) $(CFLAGS) -c $(SRC_DIR)/constraint_solver/constraints.cc $(OBJ_OUT)$(OBJ_DIR)$Sconstraint_solver$Sconstraints.$O + $(OBJ_DIR)/constraint_solver/count_cst.$O: \ $(SRC_DIR)/constraint_solver/count_cst.cc \ $(SRC_DIR)/constraint_solver/constraint_solver.h \ @@ -2933,6 +2918,7 @@ $(OBJ_DIR)/constraint_solver/local_search.$O: \ $(SRC_DIR)/base/commandlineflags.h \ $(SRC_DIR)/base/hash.h \ $(SRC_DIR)/base/integral_types.h \ + $(SRC_DIR)/base/join.h \ $(SRC_DIR)/base/logging.h \ $(SRC_DIR)/base/macros.h \ $(SRC_DIR)/base/map_util.h \ @@ -3002,11 +2988,13 @@ $(OBJ_DIR)/constraint_solver/routing.$O: \ $(SRC_DIR)/constraint_solver/routing.cc \ $(GEN_DIR)/constraint_solver/model.pb.h \ $(SRC_DIR)/constraint_solver/routing.h \ + $(SRC_DIR)/constraint_solver/routing_neighborhoods.h \ $(SRC_DIR)/base/callback.h \ $(SRC_DIR)/base/casts.h \ $(SRC_DIR)/base/commandlineflags.h \ $(SRC_DIR)/base/hash.h \ $(SRC_DIR)/base/integral_types.h \ + $(SRC_DIR)/base/join.h \ $(SRC_DIR)/base/logging.h \ $(SRC_DIR)/base/map_util.h \ $(SRC_DIR)/base/stl_util.h \ diff --git a/makefiles/Makefile.java.mk b/makefiles/Makefile.java.mk index 48bf00cdec..3fcab392c2 100755 --- a/makefiles/Makefile.java.mk +++ b/makefiles/Makefile.java.mk @@ -4,10 +4,10 @@ JAVA_ORTOOLS_LIBS= $(LIB_DIR)/com.google.ortools.jar $(LIB_DIR)/$(LIB_PREFIX)jniortools.$(JNI_LIB_EXT) -$(GEN_DIR)/constraint_solver/constraint_solver_java_wrap.cc: $(SRC_DIR)/constraint_solver/java/constraint_solver.swig $(SRC_DIR)/constraint_solver/java/routing.swig $(SRC_DIR)/base/base.swig $(SRC_DIR)/util/java/vector.swig $(SRC_DIR)/base/base.swig $(SRC_DIR)/util/java/proto.swig $(ROUTING_DEPS) +$(GEN_DIR)/constraint_solver/constraint_solver_java_wrap.cc: $(SRC_DIR)/constraint_solver/java/constraint_solver.swig $(SRC_DIR)/constraint_solver/java/routing.swig $(SRC_DIR)/base/base.swig $(SRC_DIR)/util/java/vector.swig $(SRC_DIR)/base/base.swig $(SRC_DIR)/util/java/proto.swig $(CP_DEPS) $(SRC_DIR)/constraint_solver/routing.h $(SWIG_BINARY) -I$(INC_DIR) -c++ -java -o $(GEN_DIR)$Sconstraint_solver$Sconstraint_solver_java_wrap.cc -package com.google.ortools.constraintsolver -module operations_research_constraint_solver -outdir $(GEN_DIR)$Scom$Sgoogle$Sortools$Sconstraintsolver $(SRC_DIR)$Sconstraint_solver$Sjava$Srouting.swig -$(OBJ_DIR)/swig/constraint_solver_java_wrap.$O: $(GEN_DIR)/constraint_solver/constraint_solver_java_wrap.cc $(ROUTING_DEPS) +$(OBJ_DIR)/swig/constraint_solver_java_wrap.$O: $(GEN_DIR)/constraint_solver/constraint_solver_java_wrap.cc $(CP_DEPS) $(SRC_DIR)/constraint_solver/routing.h $(CCC) $(JNIFLAGS) $(JAVA_INC) -c $(GEN_DIR)$Sconstraint_solver$Sconstraint_solver_java_wrap.cc $(OBJ_OUT)$(OBJ_DIR)$Sswig$Sconstraint_solver_java_wrap.$O $(GEN_DIR)/algorithms/knapsack_solver_java_wrap.cc: $(SRC_DIR)/algorithms/java/knapsack_solver.swig $(SRC_DIR)/base/base.swig $(SRC_DIR)/util/java/vector.swig $(SRC_DIR)/algorithms/knapsack_solver.h @@ -403,4 +403,4 @@ clean_java: -$(DEL) $(OBJ_DIR)$Scom$Sgoogle$Sortools$Salgorithms$S*.class -$(DEL) $(OBJ_DIR)$Scom$Sgoogle$Sortools$Slinearsolver$S*.class -$(DEL) $(OBJ_DIR)$Scom$Sgoogle$Sortools$Ssamples$S*.class - -$(DEL) $(OBJ_DIR)$Sswig$S*java_wrap.$O \ No newline at end of file + -$(DEL) $(OBJ_DIR)$Sswig$S*java_wrap.$O diff --git a/makefiles/Makefile.port b/makefiles/Makefile.port index 7c7828d6b1..cb15c8f656 100755 --- a/makefiles/Makefile.port +++ b/makefiles/Makefile.port @@ -90,7 +90,7 @@ endif # Windows specific part. ifeq ("$(SYSTEM)","win") # Detect 32/64bit - ifeq ("$(Platform)", "X64") + ifeq ("$(Platform)", "X64") # Visual Studio 2015 64 bit PLATFORM = WIN64 PTRLENGTH = 64 CMAKE_SUFFIX = Win64 @@ -99,13 +99,23 @@ ifeq ("$(SYSTEM)","win") GLPK_PLATFORM = w64 NETPLATFORM = x64 else - PLATFORM = Win32 - PTRLENGTH = 32 - CMAKE_SUFFIX = - ARCH = - CBC_PLATFORM_PREFIX = Win32 - GLPK_PLATFORM = w32 - NETPLATFORM = x86 + ifeq ("$(Platform)", "x64") # Visual studio 2013 64 bit + PLATFORM = WIN64 + PTRLENGTH = 64 + CMAKE_SUFFIX = Win64 + ARCH= /DARCH_K8 + CBC_PLATFORM_PREFIX = x64 + GLPK_PLATFORM = w64 + NETPLATFORM = x64 + else # Visual Studio 32 bit (soon obsolete) + PLATFORM = Win32 + PTRLENGTH = 32 + CMAKE_SUFFIX = + ARCH = + CBC_PLATFORM_PREFIX = Win32 + GLPK_PLATFORM = w32 + NETPLATFORM = x86 + endif endif # Detect visual studio version diff --git a/makefiles/Makefile.third_party.unix.mk b/makefiles/Makefile.third_party.unix.mk index 6c19213e81..0352ffed3c 100644 --- a/makefiles/Makefile.third_party.unix.mk +++ b/makefiles/Makefile.third_party.unix.mk @@ -1,7 +1,7 @@ # SVN tags of dependencies to checkout. GFLAGS_TAG = 2.1.2 -PROTOBUF_TAG = 3.0.0 +PROTOBUF_TAG = 3.2.0 CBC_TAG = 2.9.8 SWIG_TAG = 3.0.12 PCRE_TAG = 8.37 diff --git a/makefiles/Makefile.third_party.win.mk b/makefiles/Makefile.third_party.win.mk index d8554fa22b..28b7150eec 100644 --- a/makefiles/Makefile.third_party.win.mk +++ b/makefiles/Makefile.third_party.win.mk @@ -1,6 +1,6 @@ # tags of dependencies to checkout. GFLAGS_TAG = master -PROTOBUF_TAG = 3.0.0 +PROTOBUF_TAG = 3.2.0 CBC_TAG = 2.9.8 ZLIB_TAG = 1.2.11 ZLIB_ARCHIVE_TAG = 1211 diff --git a/src/base/hash.h b/src/base/hash.h index fc4889bfef..de773a8500 100644 --- a/src/base/hash.h +++ b/src/base/hash.h @@ -389,8 +389,8 @@ namespace stdext { template <> inline size_t hash_value>( const std::pair& a) { - PairIntHasher pairIntHasher; - return pairIntHasher(a); + PairInt64Hasher pairInt64Hasher; + return pairInt64Hasher(a); } } // namespace stdext #endif // _MSC_VER diff --git a/src/constraint_solver/constraint_solveri.h b/src/constraint_solver/constraint_solveri.h index 8493efd19e..430fc52483 100644 --- a/src/constraint_solver/constraint_solveri.h +++ b/src/constraint_solver/constraint_solveri.h @@ -2079,8 +2079,12 @@ class CpModelLoader { // Returns stored integer expression. IntExpr* IntegerExpression(int index) const; + // Returns the number of stored integer expressions. + int NumIntegerExpressions() const { return expressions_.size(); } // Returns stored interval variable. IntervalVar* IntervalVariable(int index) const; + // Returns the number of stored interval variables. + int NumIntervalVariables() const { return intervals_.size(); } #if !defined(SWIG) diff --git a/src/sat/integer.cc b/src/sat/integer.cc index 2b06897a27..dd902a9916 100644 --- a/src/sat/integer.cc +++ b/src/sat/integer.cc @@ -1177,7 +1177,7 @@ std::function FirstUnassignedVarAtItsMinHeuristic( .Index(); } } - return kNoLiteralIndex; + return LiteralIndex(kNoLiteralIndex); }; } @@ -1197,7 +1197,7 @@ std::function UnassignedVarWithLowestMinAtItsMinHeuristic( candidate_lb = lb; } } - if (candidate == kNoIntegerVariable) return kNoLiteralIndex; + if (candidate == kNoIntegerVariable) return LiteralIndex(kNoLiteralIndex); return integer_encoder ->GetOrCreateAssociatedLiteral( IntegerLiteral::LowerOrEqual(candidate, candidate_lb)) diff --git a/src/sat/integer.h b/src/sat/integer.h index c1c0315366..84f2adb86f 100644 --- a/src/sat/integer.h +++ b/src/sat/integer.h @@ -918,7 +918,9 @@ class LiteralViews { explicit LiteralViews(Model* model) : model_(model) {} static LiteralViews* CreateInModel(Model* model) { - return new LiteralViews(model); + LiteralViews* const views = new LiteralViews(model); + model->TakeOwnership(views); + return views; } IntegerVariable GetIntegerView(const Literal lit) { diff --git a/src/sat/intervals.h b/src/sat/intervals.h index 8984e6128e..1b3a95e4c9 100644 --- a/src/sat/intervals.h +++ b/src/sat/intervals.h @@ -137,6 +137,7 @@ class SchedulingConstraintHelper { // Note that for tasks with variable durations, we don't necessarily have // duration-min between the the XXX-min and XXX-max value. IntegerValue DurationMin(int t) const; + IntegerValue DurationMax(int t) const; IntegerValue StartMin(int t) const; IntegerValue StartMax(int t) const; IntegerValue EndMin(int t) const; @@ -240,6 +241,12 @@ inline IntegerValue SchedulingConstraintHelper::DurationMin(int t) const { : integer_trail_->LowerBound(duration_vars_[t]); } +inline IntegerValue SchedulingConstraintHelper::DurationMax(int t) const { + return duration_vars_[t] == kNoIntegerVariable + ? fixed_durations_[t] + : integer_trail_->UpperBound(duration_vars_[t]); +} + inline IntegerValue SchedulingConstraintHelper::StartMin(int t) const { return integer_trail_->LowerBound(start_vars_[t]); } @@ -340,6 +347,19 @@ inline std::function SizeVar( }; } +inline std::function IsOptional(IntervalVariable v) { + return [=](const Model& model) { + return model.Get()->IsOptional(v); + }; +} + +inline std::function IsPresentLiteral( + IntervalVariable v) { + return [=](const Model& model) { + return model.Get()->IsPresentLiteral(v); + }; +} + inline std::function NewInterval(int64 min_start, int64 max_end, int64 size) { diff --git a/src/sat/linear_programming_constraint.cc b/src/sat/linear_programming_constraint.cc index 48b72501f4..5a9cfd1e35 100644 --- a/src/sat/linear_programming_constraint.cc +++ b/src/sat/linear_programming_constraint.cc @@ -25,6 +25,8 @@ DEFINE_bool(lp_constraint_use_dual_ray, true, namespace operations_research { namespace sat { +const double LinearProgrammingConstraint::kEpsilon = 1e-6; + LinearProgrammingConstraint::LinearProgrammingConstraint( IntegerTrail* integer_trail) : integer_trail_(integer_trail) { diff --git a/src/sat/linear_programming_constraint.h b/src/sat/linear_programming_constraint.h index 8b372c5828..0ae774fd56 100644 --- a/src/sat/linear_programming_constraint.h +++ b/src/sat/linear_programming_constraint.h @@ -127,7 +127,7 @@ class LinearProgrammingConstraint : public PropagatorInterface { glop::Fractional GetVariableValueAtCpScale(glop::ColIndex var); // TODO(user): use solver's precision epsilon. - constexpr static double kEpsilon = 1e-6; + static const double kEpsilon; // Underlying LP solver API. glop::LinearProgram lp_data_; diff --git a/src/sat/timetable.cc b/src/sat/timetable.cc index 3295e95168..7cb74e8636 100644 --- a/src/sat/timetable.cc +++ b/src/sat/timetable.cc @@ -35,9 +35,16 @@ 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); - in_profile_.resize(num_tasks_); scp_.reserve(num_tasks_); ecp_.reserve(num_tasks_); + is_in_profile_.resize(num_tasks_); + in_profile_.reserve(num_tasks_); + // Reversible set of tasks to consider for propagation. + num_tasks_to_sweep_ = num_tasks_; + tasks_to_sweep_.resize(num_tasks_); + for (int t = 0; t < num_tasks_; ++t) { + tasks_to_sweep_[t] = t; + } } void TimeTablingPerTask::RegisterWith(GenericLiteralWatcher* watcher) { @@ -47,6 +54,8 @@ void TimeTablingPerTask::RegisterWith(GenericLiteralWatcher* watcher) { for (int t = 0; t < num_tasks_; t++) { watcher->WatchLowerBound(demand_vars_[t], id); } + // Reversible number of tasks to consider for propagation. + watcher->RegisterReversibleInt(id, &num_tasks_to_sweep_); } bool TimeTablingPerTask::Propagate() { @@ -75,19 +84,23 @@ bool TimeTablingPerTask::BuildProfile() { scp_.clear(); ecp_.clear(); + in_profile_.clear(); // Build start of compulsory part events. for (int i = num_tasks_ - 1; i >= 0; --i) { const auto task_time = by_decreasing_start_max[i]; const int t = task_time.task_index; - in_profile_[t] = + is_in_profile_[t] = helper_->IsPresent(t) && task_time.time < helper_->EndMin(t); - if (in_profile_[t]) scp_.push_back(task_time); + if (is_in_profile_[t]) { + in_profile_.push_back(t); + scp_.push_back(task_time); + } } // Build end of compulsory part events. for (int i = 0; i < num_tasks_; ++i) { - if (in_profile_[by_increasing_end_min[i].task_index]) { + if (is_in_profile_[by_increasing_end_min[i].task_index]) { ecp_.push_back(by_increasing_end_min[i]); } } @@ -189,17 +202,38 @@ void TimeTablingPerTask::ReverseProfile() { bool TimeTablingPerTask::SweepAllTasks() { // Tasks with a lower or equal demand will not be pushed. const IntegerValue min_demand = CapacityMax() - profile_max_height_; - for (int t = 0; t < num_tasks_; ++t) { - // Note: We still push the optional task that may be present. It is OK to - // propagate the bounds of such tasks. They should become unperformed if - // the bounds are no longer consistent. - if (DemandMin(t) <= min_demand || helper_->DurationMin(t) == 0) continue; - if (helper_->IsAbsent(t)) continue; - if (helper_->StartMin(t) != helper_->StartMax(t) && !SweepTask(t)) { - return false; + 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 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; + // - it is absent. + if ((fixed_start && fixed_end) || helper_->DurationMax(t) == 0 || + DemandMax(t) == 0 || helper_->IsAbsent(t)) { + // Remove the task from the set of tasks to sweep. + num_tasks_to_sweep_--; + tasks_to_sweep_[i] = tasks_to_sweep_[num_tasks_to_sweep_]; + tasks_to_sweep_[num_tasks_to_sweep_] = t; + continue; } + // A task does not have to be considered for propagation in this particular + // iteration if it respects one of these conditions: + // - its start variable is fixed; + // - its minimum demand cannot lead to a resource overload; + // - its minimum duration is 0. + if (fixed_start || DemandMin(t) <= min_demand || + helper_->DurationMin(t) == 0) { + continue; + } + + if (!SweepTask(t)) return false; } + return true; } @@ -249,7 +283,7 @@ bool TimeTablingPerTask::SweepTask(int task_id) { new_start_min = profile_[rec_id].end; if (start_max < new_start_min) { new_start_min = start_max; - overload = !in_profile_[task_id]; + overload = !is_in_profile_[task_id]; } new_end_min = std::max(new_end_min, new_start_min + duration_min); @@ -294,13 +328,12 @@ bool TimeTablingPerTask::UpdateStartingTime(int task_id, IntegerValue left, void TimeTablingPerTask::AddProfileReason(IntegerValue left, IntegerValue right) { - for (int t = 0; t < num_tasks_; ++t) { + for (const int t : in_profile_) { const IntegerValue start_max = helper_->StartMax(t); const IntegerValue end_min = helper_->EndMin(t); - // Do not consider the task if it does not overlap [left, right), if it is - // absent, or if it does not have a mandatory part. - if (end_min <= left || right <= start_max || !in_profile_[t]) continue; + // Do not consider the task if it does not overlap [left, right). + if (end_min <= left || right <= start_max) continue; helper_->AddPresenceReason(t); helper_->AddStartMaxReason(t, std::max(left, start_max)); diff --git a/src/sat/timetable.h b/src/sat/timetable.h index 7c6abab82e..a25cf8d612 100644 --- a/src/sat/timetable.h +++ b/src/sat/timetable.h @@ -88,6 +88,10 @@ class TimeTablingPerTask : public PropagatorInterface { return integer_trail_->LowerBound(demand_vars_[task_id]); } + IntegerValue DemandMax(int task_id) const { + return integer_trail_->UpperBound(demand_vars_[task_id]); + } + // Number of tasks. const int num_tasks_; @@ -110,12 +114,21 @@ class TimeTablingPerTask : public PropagatorInterface { // True if the corresponding task is part of the profile, i.e., it has a // mandatory part and is not optional. - std::vector in_profile_; + std::vector is_in_profile_; + + // Tasks that are part of the profile. In other words, this vector contains + // all the tasks for which is_in_profile_ is true. + std::vector in_profile_; // True if the last call of the propagator has filtered the domain of a task // 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_; + DISALLOW_COPY_AND_ASSIGN(TimeTablingPerTask); }; diff --git a/src/util/piecewise_linear_function.cc b/src/util/piecewise_linear_function.cc index 939b981c69..6fc9a4dc79 100644 --- a/src/util/piecewise_linear_function.cc +++ b/src/util/piecewise_linear_function.cc @@ -351,53 +351,58 @@ PiecewiseLinearFunction* PiecewiseLinearFunction::CreateFullDomainFunction( PiecewiseLinearFunction* PiecewiseLinearFunction::CreateOneSegmentFunction( int64 point_x, int64 point_y, int64 slope, int64 other_point_x) { - return new PiecewiseLinearFunction( - {PiecewiseSegment(point_x, point_y, slope, other_point_x)}); + std::vector segments = + {PiecewiseSegment(point_x, point_y, slope, other_point_x)}; + return new PiecewiseLinearFunction(segments); } PiecewiseLinearFunction* PiecewiseLinearFunction::CreateRightRayFunction( int64 point_x, int64 point_y, int64 slope) { - return new PiecewiseLinearFunction( - {PiecewiseSegment(point_x, point_y, slope, kint64max)}); + std::vector segments = + {PiecewiseSegment(point_x, point_y, slope, kint64max)}; + return new PiecewiseLinearFunction(std::move(segments)); } PiecewiseLinearFunction* PiecewiseLinearFunction::CreateLeftRayFunction( int64 point_x, int64 point_y, int64 slope) { - return new PiecewiseLinearFunction( - {PiecewiseSegment(point_x, point_y, slope, kint64min)}); + std::vector segments = + {PiecewiseSegment(point_x, point_y, slope, kint64min)}; + return new PiecewiseLinearFunction(std::move(segments)); + } PiecewiseLinearFunction* PiecewiseLinearFunction::CreateFixedChargeFunction( int64 slope, int64 value) { - std::vector segments; + std::vector segments = + {PiecewiseSegment(0, 0, 0, kint64min), + PiecewiseSegment(0, value, slope, kint64max)}; CHECK_GE(slope, 0); CHECK_GE(value, 0); - return new PiecewiseLinearFunction( - {PiecewiseSegment(0, 0, 0, kint64min), - PiecewiseSegment(0, value, slope, kint64max)}); + return new PiecewiseLinearFunction(std::move(segments)); } PiecewiseLinearFunction* PiecewiseLinearFunction::CreateEarlyTardyFunction( int64 reference, int64 earliness_slope, int64 tardiness_slope) { - std::vector segments; + std::vector segments = + {PiecewiseSegment(reference, 0, -earliness_slope, kint64min), + PiecewiseSegment(reference, 0, tardiness_slope, kint64max)}; CHECK_GE(earliness_slope, 0); CHECK_GE(tardiness_slope, 0); - return new PiecewiseLinearFunction( - {PiecewiseSegment(reference, 0, -earliness_slope, kint64min), - PiecewiseSegment(reference, 0, tardiness_slope, kint64max)}); + return new PiecewiseLinearFunction(std::move(segments)); } PiecewiseLinearFunction* PiecewiseLinearFunction::CreateEarlyTardyFunctionWithSlack( int64 early_slack, int64 late_slack, int64 earliness_slope, int64 tardiness_slope) { - std::vector segments; - CHECK_GE(earliness_slope, 0); - CHECK_GE(tardiness_slope, 0); - return new PiecewiseLinearFunction( + std::vector segments = {PiecewiseSegment(early_slack, 0, -earliness_slope, kint64min), PiecewiseSegment(early_slack, 0, 0, late_slack), - PiecewiseSegment(late_slack, 0, tardiness_slope, kint64max)}); + PiecewiseSegment(late_slack, 0, tardiness_slope, kint64max)}; + + CHECK_GE(earliness_slope, 0); + CHECK_GE(tardiness_slope, 0); + return new PiecewiseLinearFunction(std::move(segments)); } bool PiecewiseLinearFunction::InDomain(int64 x) const {